深入理解JVM(③)Java的锁优化 (2)

HotSpot虚拟机对象头Mark Word

轻量级锁工作过程 轻量级锁加锁

在代码即将进入同步块的时候,如果此同步对象没有被锁定(标志位“01”状态),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝。

然后,虚拟机将使用CAS操作尘世把对象的Mark Word 更新为执行Lock Record 的指针。

如果这个更新操作成功了,即代表线程拥有了这个对象的锁,并且对象Mark Word的锁标志位(Mark Word的最后两个比特)将转变为“00”,表示此对象处于轻量级锁定状态。

如果这个更新操作失败了,那就意味着至少存在一条线程与当前线程竞争获取该对象的锁。

上面说了轻量级锁的加锁过程了,它的解锁过程也同样是通过CAS操作来进行的。

如果对象的Mark Word 仍然指向线程的锁记录,那就用CAS操作把对象当前的Mark Wrod和线程中复制的Displaced Mark Word替换回来。

加入能够替换,那整个同步过程就顺利完成了;

如果替换失败,则说明有其他线程尝试过滤获取该锁,就要在释放锁的同时,唤醒被挂起的线程。

轻量级锁总结:
轻量级锁能提升新恒信性能的依据是:“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”。
如果没有竞争,轻量级锁便通过CAS操作成功避免了使用互斥量的开销;但如果确实存在锁竞争,除了互斥量的本身开销外,还额外发生了CAS操作的开销。因此在有竞争的情况下,轻量级锁反而会比传统的重量级锁更慢。

偏向锁 偏向锁的意义:

偏向锁的目的是消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能。
如果说轻量级锁是在无竞争的情况下使用CAS操作消除同步使用的互斥量,那偏向锁就是咋无竞争的情况下把整个同步都消除掉,连CAS操作都不去做了。

偏向锁的定义:

这个锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁一直没有被其他线程获取,则持有偏向锁的线程将用于不需要在进行同步。

偏向锁加锁过程

当虚拟机启动了偏向锁,那么当锁对象第一次被线程获取的时候,虚拟机将会把对象头中的标志位设置为“01”、把偏向模式设置为“1”,表示进入偏向模式。

同时使用CAS操作把获取到这个锁的线程ID记录在对象的Mark Word之中。

如果CAS操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块是,虚拟机都可以不再进行任何同步操作。

偏向锁解锁过程

当出现另外一个线程区尝试获取这个锁的情况,偏向模式就马上宣告结束。根据锁对象目前是否处于被锁定的状态决定是否撤销偏向(偏向模式设置为“0”),撤销后标志位恢复到未锁定(标志位“01”)或轻量级锁定(标志位为“00”)的状态,后续的同步操作就按照上面介绍的轻量级锁那样去执行。

感悟:

《深入理解Java虚拟机(第三版)》这本书,差不多算是看完了,笔记也都记录下来了,还是有几章个人觉得并不重要的章节给忽略掉了,所以就没有做笔记。这次的感觉比第一次读第二版的时候有了更深的理解,也接触到了新的知识,例如以前没研究过Java9的模块化的知识。
这次陆陆续续算上在博客上做笔记也是大概用了一个多月将近2个月,感觉比读第二版的时候,速度快了些。
每次准备换工作的时候,都是第一个想起来要看一遍这本书。但是最近两年的情况好像有所不同了,现在各大互联网公司面试必备的条件就是手撕算法,所以我也深刻的意识到了,想要出去面试光看这本书是远远不够的,因此后续的时间里,我将要开启算法的学习历程了,大家也一起加油吧!
还是那句话,我们只需努力,剩下的交给时间就好了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsyjs.html