Synchronized和Lock的区别

本文参考:
1.https://zhuanlan.zhihu.com/p/180469207;
2.https://javaguide.cn/java/concurrent/java-concurrent-questions-02.html#synchronized-%E5%92%8C-reentrantlock-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB

作为一道常见面试题,我们首先需要清楚这里的Lock是指哪个Lock?
我们在IDEA中输入Lock会出现三个Lock相关的类,其中一个是接口,其余两个是类。
在这里插入图片描述
1.先看sun.misc中的Lock类,源码如下:

package sun.misc;

public class Lock {
    private boolean locked = false;

    public Lock() {
    }

    public final synchronized void lock() throws InterruptedException {
        while(this.locked) {
            this.wait();
        }

        this.locked = true;
    }

    public final synchronized void unlock() {
        this.locked = false;
        this.notifyAll();
    }
}

可以看到这个Lock底层还是由synchronized关键字实现的,所以面试问的应该不是这个Lock;

2.再看com.sun下面的这个包,源码如下:

package com.sun.deploy.util;

public class SyncAccess {
    public static final int READ_OP = 2;
    public static final int WRITE_OP = 4;
    public static final int SHARED_READ_MODE = 8;
    private int lockedOP = 0;
    private Object syncObj = new Object();
    private int mode;

    public SyncAccess(int var1) {
        this.mode = var1;
    }

    public Lock lock(int var1) {
        boolean var2 = false;
        byte var3;
        if (var1 == 2 && (this.mode & 8) != 0) {
            var3 = 4;
        } else {
            var3 = 6;
        }

        return new Lock(var3, var1);
    }

    private void acquireLock(int var1, int var2) {
        synchronized(this.syncObj) {
            while((this.lockedOP & var1) != 0) {
                try {
                    this.syncObj.wait();
                } catch (InterruptedException var6) {
                }
            }

            this.lockedOP |= var2;
        }
    }

    private void releaseLock(int var1) {
        synchronized(this.syncObj) {
            this.lockedOP &= ~var1;
            this.syncObj.notifyAll();
        }
    }

    public class Lock {
        private int op;

        private Lock(int var2, int var3) {
            this.op = var3;
            SyncAccess.this.acquireLock(var2, var3);
        }

        public void release() {
            SyncAccess.this.releaseLock(this.op);
        }
    }
}

同样是由synchronized实现的上锁,因此也不是这个。

3.那么就只剩下concurrent包下的Lock接口了,源码如下:

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

而我们常见的Lock实现类ReentrantLock类,可以作为切入点进行对比。

Lock lock = new ReentrantLock();

1.synchronized和Lock的区别

1.底层实现来看:
synchronized: 底层使用指令码方式来控制锁的,映射成字节码指令就是增加来两个指令:monitorenter和monitorexit。当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取锁则阻塞;当遇到monitorexit指令时锁计数器-1,如果计数器为0表示释放了锁;

Lock: 是一个接口,提供了多种实现类,底层是CAS乐观锁;比如ReentrantLock,依赖AbstractQueuedSynchronizer类,把所有的请求线程构成一个CLH队列。而对该队列的操作均通过Lock-Free(CAS)操作。

2.用法:
synchronized: 在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

Lock: 一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁

3.调度:
synchronized: 使用Object对象本身的wait 、notify、notifyAll调度机制;

Lock: 可以使用Condition进行线程之间的调度;

4.锁的类型:
synchronized: 可重入 不可中断 非公平;

Lock: 可重入 可中断 可公平(两者皆可);

5.锁的状态:
synchronized: 无法判断;

Lock: 可以判断;

6.锁的释放(死锁产生)
synchronized: 在发生异常时候会自动释放占有的锁,因此不会出现死锁;

Lock: 发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生;

2.ReentrantLock与synchronized的异同

1.两者都是可重入锁;JDK 提供的所有现成的 Lock 实现类,包括 synchronized 关键字锁都是可重入的;

2.synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API;

3.ReentrantLock 比 synchronized 增加了一些高级功能:
等待可中断 : ReentrantLock提供了一种能够中断等待锁的线程的机制,通过 lock.lockInterruptibly() 来实现这个机制。也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。

可实现公平锁 : ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。ReentrantLock默认情况是非公平的,可以通过 ReentrantLock类的ReentrantLock(boolean fair)构造方法来指定是否是公平的。

可实现选择性通知(锁可以绑定多个条件): synchronized关键字与wait()和notify()/notifyAll()方法相结合可以实现等待/通知机制。ReentrantLock类当然也可以实现,但是需要借助于Condition接口与newCondition()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值