ReentrantLo区别解析·比如·解级巧技

ReentrantLock原理和synchronized区别解析


一、底层实现上

Java中的synchronized是通过JVM层面的锁,也就是Java关键字来完成的,它是通过monitor对象来实现的,比如monitorenter和monitorexit。只有当对象在同步块或同步方法中时,才能调用wait/notify方法。而ReentrantLock则是从Java 1.5开始提供的API层面的锁,它的实现更依赖于CAS(CompareAndSwap)自旋机制来保证线程操作的原子性和数据的可见性。

同步锁 ReentrantLock
底层实现 JVM层面的锁(monitor对象)
锁的升级 CAS自旋机制和volatile保证

二、是否可手动释放

使用synchronized,用户不需要手动释放锁,当synchronized代码执行完成后,系统会自动释放锁。而ReentrantLock则需要用户手动释放锁,如果不释放,可能会导致死锁。一般可以通过lock()和unlock()方法配合try/finally语句块来完成,这样使用起来更灵活。

三、是否可中断

synchronized是不可中断的锁,除非加锁的代码中出现异常或正常执行完成。而ReentrantLock是可以被中断的,可以通过trylock(long timeout, TimeUnit unit)设置超时方法,或者将lockInterruptibly()放到代码块中,然后通过调用interrupt方法进行中断。

四、是否公平锁

synchronized是非公平锁,而ReentrantLock可以设置为公平锁或非公平锁。通过在创建ReentrantLock时传入一个布尔值来选择,默认为false,即非公平锁;如果传入true,则为公平锁。

五、锁是否可绑定条件Condition

synchronized不支持绑定条件,而ReentrantLock可以通过绑定Condition来使用await()/signal()方法,实现线程的精确唤醒,而不是像synchronized那样通过Object类的wait()/notify()/notifyAll()方法来随机唤醒一个线程或者唤醒全部线程。

六、锁的对象

synchronized锁的是对象,锁是保存在对象头里面的,根据对象头数据来标识是否有线程获得锁/争抢锁。而ReentrantLock锁的是线程,根据进入的线程和int类型的state标识锁的获得/争抢。

延伸阅读

实例变量是面向对象编程中的一个术语,它表示某个类的对象实例的属性或状态。每个类的对象实例都有其自己的实例变量集合,一个实例的变量值不会影响另一个实例的变量值。