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标识锁的获得/争抢。
延伸阅读
实例变量是面向对象编程中的一个术语,它表示某个类的对象实例的属性或状态。每个类的对象实例都有其自己的实例变量集合,一个实例的变量值不会影响另一个实例的变量值。