Java 中第一次被 synchrnoized 上锁的对象的对象头到底怎么变??

2020-04-24 14:14:15 +08:00
 Newyorkcity

以下内容均引自《深入理解 JVM 》第二版,周志明先生著。

简单地介绍了对象的内存布局后,我们把话题返回到轻量级锁的执行过程上。在代码进入同步块的时候,如果此同步对象没有被锁定(锁标志位为“01”状态),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录( Lock record )的空间,用于存储锁对象目前的 Mark Word 的拷贝(官方把这份拷贝加了一个 Displaced 前缀,即 Displaced Mark Word ),这时候线程堆栈与对象头的状态如图 13-3 所示。 然后,虚拟机将使用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock record 的指针。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象 Mark Word 的锁标志位( Mark Word 的最后 2bit )将转变为“00”,即表示此对象处于轻量级锁定状态,这时候线程堆栈与对象头的状态如图 13-4 所示。

上面这个引用出自『 13.3.4 轻量级锁 』

如果读者读懂了前面轻量级锁中关于对象头 Mark Word 与线程之间的操作过程,那偏向锁的原理理解起来就会很简单。假设当前虚拟机启用了偏向锁(启用参数-XX:+ UseBiased Locking,这是 JDK1.6 的默认值),那么,当锁对象第一次被线程获取的时候,虚拟机将会把对象头中的标志位设为“01”,即偏向模式。同时使用 CAS 操作把获取到这个锁的线程的 DD 记录在对象的 Mark Word 之中,如果 CAS 操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不再进行任何同步操作(例如 Locking 、Unlocking 及对 Mark Word 的 Update 等)

这一段出自『 13.3.5 偏向锁 』

一个即将第一次因为 synchronized 被上锁的对象,对象头的末两个 bit 是 01

(1)然后,虚拟机将使用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock record 的指针。

(2)那么,当锁对象第一次被线程获取的时候,虚拟机将会把对象头中的标志位设为“01”(第一次被获取的话不是自然而然就是 01 么,为何还要特别设置),即偏向模式。同时使用 CAS 操作把获取到这个锁的线程的 DD 记录在对象的 Mark Word 之中,

( 1 ) ( 2 ) 中有两个设置到对象头中的内容。。。

1100 次点击
所在节点    问与答
3 条回复
hitsmaxft
2020-04-24 15:58:29 +08:00
一个对象创建的时候直接置为 01 不就行了. 怎么变是后面加锁操作的时候需要考虑的.
Newyorkcity
2020-04-24 16:37:08 +08:00
@hitsmaxft 所以是怎么个考虑呢。。
DsuineGP
2020-04-24 19:09:22 +08:00
第一次进入同步区的线程拿到的是 01 偏向锁,竞争不激烈的情况下性能好。
当多个线程竞争的时候偏向锁会膨胀成 10 重量级锁,也是我们常说的“互斥锁”。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/665664

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX