以下内容均引自《深入理解 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 ) 中有两个设置到对象头中的内容。。。
1
hitsmaxft 2020-04-24 15:58:29 +08:00
一个对象创建的时候直接置为 01 不就行了. 怎么变是后面加锁操作的时候需要考虑的.
|
2
Newyorkcity OP @hitsmaxft 所以是怎么个考虑呢。。
|
3
DsuineGP 2020-04-24 19:09:22 +08:00 1
第一次进入同步区的线程拿到的是 01 偏向锁,竞争不激烈的情况下性能好。
当多个线程竞争的时候偏向锁会膨胀成 10 重量级锁,也是我们常说的“互斥锁”。 |