您的位置 首页 java

JAVA中ReentrantLock与synchronized如何加锁解锁及原理和区别?

ReentrantLock原理

加锁: 首先,它是基于 AQS (抽像队例 同步器 )来实现的,我们先记住AQS中的关建字 state 线程 标记 队例 AQS后面我们会讲 。当我们通过reentrantLock.lock();来加锁时,通过compareAndSetState来对state进行操作,结果成功了就得到了锁,用的CAS线程安全方式。如果没成功,判断线程标记是否是当前线程,如果是表示重入锁,对state进行加1,如果不是,放入等待队列, park 挂起当前线程。

释放锁: 当我们通过 reentrantLock.unlock(); 来释放锁时,先拿到 state-1 ,得到一个值,然后判断释放锁的是否是当前线程,如果不是报错,是的话判断state是否等于0,如果是重入锁的话不等于0,些时只需要设置一下state的值就可以,然后如果等于0,就设置 state 的值为0,并且 unpark 释放自己next等待的线程,处理park的线程会被唤醒继续执行。

synchronized底层的原理

synchronized 底层的原理,是跟 jvm 指令和monitor有关系的,在底层编译后的jvm指令中,会有monitorenter和monitorexit两个指令。

加锁: 如果一个线程第一次synchronized那里,获取到了xx对象的monitor的锁(monitorenter指令), 计数器 加1,然后第二次synchronized那里,会再次获取xx对象的monitor的锁,这个就是重入加锁了,然后计数器会再次加1,变成2。此时,其他的线程在第一次synchronized那里,会发现说xx对象的monitor锁的计数器是大于0的,意味着被别人加锁了,然后此时线程就会进入block阻塞状态,什么都干不了,就是等着获取锁

释放锁: 接着如果退出了synchronized修饰的代码片段的范围,就会有一个monitorexit的指令,在底层,此时获取锁的线程就会对xx对象的monitor的计数器减1,重入加锁就会对应多次减1,直到计数器是0,然后后面block住阻塞的线程,会再次尝试获取锁。

它们之间的区别

主要相同点: ReentrantLock能完成synchronized所实现的所有功能。

主要不同点: ReentrantLock有比synchronized更精确的线程语义和更好的性能。但synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock要控制线程等待需要一个Condition对像进行管理await等操作,而synchronized可直接用wait等方式进行线程控制。

关于ReentrantLock与synchronized的实现原理及之间的区别,这里只是简单总结了一下,里面的知识点还有很多,如多线程操作state是安全的么?需要深入理解及获取相关资料的可留言。

下节讲解 JAVA 中的锁优化。

文章来源:智云一二三科技

文章标题:JAVA中ReentrantLock与synchronized如何加锁解锁及原理和区别?

文章地址:https://www.zhihuclub.com/182597.shtml

关于作者: 智云科技

热门文章

网站地图