前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发-ReentrantLock浅析

并发-ReentrantLock浅析

作者头像
Coder的技术之路
发布2021-05-14 14:14:46
2280
发布2021-05-14 14:14:46
举报
文章被收录于专栏:Coder的技术之路

一旦涉及到并发,就无法避免共享数据的访问问题,解决的方法有synchronized关键 字、锁(重量级锁、轻量级锁、偏向锁...)、信号量等 以及更高级的无锁实现。 今天我就先简单的阐述一下,Java锁中的 比较 高效的重入锁--ReetrantLock . 1.synchronized 为啥慢 我们反编译一下 带有同步块的代码,可以看到

在3 和 13 行,被插入了两条监视器的机器指令,而monitor指令传说是用操作系统的 Mutex Lock来实现的(没来得及具体考证),用操作系统来实现线程切换,就需要在用户 态和核心态间转换,开销很大。普遍被称作重量级锁。 2.为了减小这种系统开销,我们想要吧加锁的行为从系统级别移到类上,于是有了Lock, 第一种就是ReentrantLock.ReentrantLock被叫做重入锁,意思是线程可以进入任何 一个它已经拥有的锁所同步着的代码块。 如下图,

如果是不可重入的锁,就会产生死锁,因为第一个方法调用了第二个方法,但是第一个方 法已经获取了锁,第二个方法无法获取当前锁,从而产生死锁 ; 而如果是可重入锁, 就不会产生死锁问题。test2依然可以获取到lock. 当然,这个代表了广义上的可重入,ReentrantLock只能说是其中一种。 ReentrantLock的内核是AbstractQueuedSynchronizer,底层实现是CAS,如果抢 占成功,逻辑是比较简单的,如图

CAS成功,则设置自己为锁的当前拥有者; 而设置不成功,则比较麻烦,大概的过程是 要再几次的进行判断,确认锁是否可用,如 果都不可用,则添加到等待队列,而重入的具体体现,就在第二步,具体含义我写在了注释里

我们看到,首先程序会获取状态量state,因为state是volatile的,所以是线程可见 的,拿到的是最新的状态,if块里和前面的抢占成功逻辑一样, 而else块里,我们看到,如果发现锁的占有者是自己,那么,会在当前的state值上加1, 加1之后的判断,是要进行溢出验证,最大可允许的重入线程数==Integer的最大值。 当然,ReentrantLock 还涉及到很多其他知识点,比如公平锁和非公平锁、等待队列 如果添加、内部类AQS的模板模式等等,在这里只是做个记录,要想完全弄清楚,还是挺不容易的,有兴趣的同学们可以看看它的源代码探究一下

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder的技术之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档