ReentrantLock与synchronized的区别

发布时间:2022-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了ReentrantLock与synchronized的区别脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

Synchronized

Synchronized 是通过对象内部的一个叫做监视器锁(monITor)来实现的,监视器锁本质又是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么 Synchronized 效率低的原因。因此,这种依赖于操作系统 Mutex Lock 所实现的锁我们称之为 “重量级锁”

同步方法通过ACC_SYNCHRONIZED 关键字隐式的对方法进行加锁。当线程要执行的方法被标注上ACC_SYNCHRONIZED时,需要先获得锁才能执行该方法。同步代码块通过monitorenter和monitorexit执行来进行加锁。当线程执行到monitorenter的时候要先获得锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。每个对象自身维护着一个被加锁次数的计数器,当计数器不为0时,只有获得锁的线程才能再次获得锁。

ReentrantLock

ReentrantLock通过原子操作和阻塞实现锁原理,一般使用lock获取锁,unlock释放锁

lock的时候可能被其他线程获得所,那么此线程会阻塞自己,关键原理底层用到Unsafe类的API: CAS和park

ReentantLock 继承接口Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。

 

Lock 主要方法1. void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经被其他线程持有, 将禁用当前线程, 直到当前线程获取到锁.2. boolean tryLock():如果锁可用, 则获取锁, 并立即返回true, 否则返回false. 该方法和lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被禁用,当前线程仍然继续往下执行代码. 而lock()方法则是一定要获取到锁, 如果锁不可用, 就一直等待, 在未获得锁之前,当前线程并不继续向下执行.3. void unlock():执行此方法时, 当前线程将释放持有的锁. 锁只能由持有者释放, 如果线程并不持有锁, 却执行该方法, 可能导致异常的发生.4. Condition newCondition():条件对象,获取等待通知组件。该组件和当前的锁绑定,当前线程只有获取了锁,才能调用该组件的await()方法,而调用后,当前线程将缩放锁。

ReentrantLock 与 synchronized

1.ReentrantLock 通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized 会被JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock 必须在finally 控制块中进行解锁操作。2. ReentrantLock 相比synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要使用ReentrantLock。

 

wait() notify() notifyAll() 和await() signal() 和 signalAll() 的区别?

在使⽤Lock之前,我们都使⽤Object+的wait和notify实现同步。

Synchronized(obj){

obj.wait://此时这个线程会释放锁。并等待其他线程唤醒才能往下执行。

}

Synchronized(obj){

obj.notify://此时这个线程会释放锁。并等待其他线程唤醒才能往下执行。

}

而Lock则是由Lock控制锁,Condition来控制被阻塞线程

// 消费者lock.lock();

condition.await();lock.unlock();

//生产者lock.lock(); condition.signal(); lock.unlock();

为了突出区别,省略了若⼲细节。区别有三点:

1.lock不再使用synchronize把同步代码包装起来

2.阻塞需要另外一个对象condition。

3.对应的方法是await和signal。

使用lock的好处就是我们可以指定条件来唤醒某个线程。而object 的唤醒是随机的

假设我们我们的需要想让a线程执行。

Lock lock = new ReentrantLock();

Condition acondition=lock.newCondition();//创建Condition

Condition bcondition=lock.newCondition();//创建Condition

可以acondition.signal().这样a线程就可以唤醒了。

 

脚本宝典总结

以上是脚本宝典为你收集整理的ReentrantLock与synchronized的区别全部内容,希望文章能够帮你解决ReentrantLock与synchronized的区别所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。