偏向锁居然也会用到lock record六:偏向锁居然也会用到lock record

哈喽,大家好,我是江湖人送外号[道格牙]的子牙老师。

近期准备写一个专栏:从Hotspot源码角度剖析synchronized。前前后后大概有10篇,会全网发,写完后整理成电子书放公众号供大家下载。对本专栏感兴趣的、希望彻彻底底学明白synchronized的小伙伴可以关注一波。电子书整理好了会通过公众号群发告知大家。我的公众号:硬核子牙。 市面上关于synchronized的资料已经很多了,我这个专栏跟那些资料有啥差别呢:

  1. 更系统。市面上目前虽然资料众多,但都是零散的。有些资料讲得东西甚至是相互冲突的,都不知道信谁的。我准备从Java层面到JVM层面到操作系统层面系统的去分析用synchronized后呈现的每个现象背后的本质。synchronized很多知识点市面上是没有资料讲的,我给它补上。
  2. 更接近真相。市面上的很多资料,有的是基于字节码解释器那块的代码yy出来的,有的是东拼西凑整合出来的,各个说的都像真的一样,把看的人搞蒙圈了。我准备从模板解释器代码入手,单步调试着研究,有些不确定的自己写代码去证明,争取分享给大家的都是本来如此的知识。不确定的地方我会标注出来。
  3. 授人以鱼不如授人以渔。我会以大家学完后能够手写出synchronized的标准来设计这个专栏。因为从我自己研究的角度来说,抛开语言的障碍,synchronized的每种机制如果让你实现你手足无措,那你还是没有真正地理解synchronized。言外之意就是你不一定要去手写,但是你在脑海中回想,比如CAS、锁膨胀、锁对象加锁解锁……你大概知道代码是怎么写的。

废话不多说,接上篇,开始卷Hotspot源码。如果你还没看上篇,墙裂都建议你先看一下。 注意:本篇文章仅适用于synchronized修饰方法这种情况,不适用于synchronized代码段。关于synchronized代码段,下篇文章。

偏向锁前的堆栈图

如果是synchronized修饰的方法,会先执行lock_method方法。这个方法做了三件事情:

  1. 根据是否是静态方法计算出锁对象,将锁对象的内存地址保持到rax寄存器中
  2. 在当前的栈帧中创建一个lock record,将锁对象的内存地址写入
  3. 调用lock_object完成加锁

lock_method执行之后的堆栈图

这个图对于后面理解偏向锁的膨胀、撤销及轻量级锁至关重要。

lock_object

这个方法这里有个判断,如果启用了偏向锁就调用biased_locking_enter。如果没有启用,或者biased_locking_enter执行结束回来,后面代码是抢占轻量级锁、轻量级锁重入、膨胀成重量级锁逻辑。后面讲轻量级锁、重量级锁细讲。

biased_locking_enter 这个方法全是汇编,我就不贴源码了,以伪代码的方式直接讲它的执行逻辑

这个方法是理解偏向锁的核心方法之一,小伙伴们一定要多看多想多悟,悟透,不然学到后面一团糟。

模板解释器那块,关于偏向锁的逻辑就详细地讲完了。接下来咱们以不同的锁类型进入偏向锁逻辑为例梳理偏向锁的执行逻辑,正好把fast_enter那块的逻辑串起来。

如果是匿名偏向锁

如果当前对象的锁状态是匿名偏向状态,按照前面讲的,会出现两种情况:CAS成功抢到了偏向锁,进入临界区执行代码。CAS失败进入slow_case。接下来把slow_case整个逻辑讲一下。 看代码执行顺序

revoke_bias 理解这个方法,堆栈图就要派上用场了

讲到这再回顾下上篇文章的这段话,是不是理解得更深刻了

抢偏向锁 这种情况跟多线程抢偏向锁抢锁失败的情况是一样的,就不重复讲了。 至此,偏向锁的核心逻辑就讲完了。其他的知识点,感兴趣的小伙伴,可以基于理解我分享的这些,去自行研究。相信小伙伴们都能征服synchronized。

系列文章

1、JVM如何执行synchronized修饰的方法

2、死磕synchronized二:系统剖析延迟偏向篇一

3、死磕synchronized三:系统剖析延迟偏向篇二

4、死磕synchronized四:系统剖析偏向锁篇一

5、死磕synchronized五:系统剖析轻量级锁

推荐阅读

1、今天聊点不一样的,百万年薪需要具备的能力 - 掘金 (juejin.cn)

2、你是不是想问,那些技术大牛是如何练成的?我来告诉你

3、深入剖析Lambda表达式的底层实现原理

结语

其实技术这个行业真的不难,如果有人带,打底子1-2年,沉淀2-3年,足矣。我自己一步步探索,走得还算顺利,大概花了七年时间。

给大家看看我写好的

猜你喜欢

转载自juejin.im/post/7036284339847430151