宝藏图,引起的一堆问题,轻量级锁的不解(Synchronized 锁的升级)
================================================================
看一看 synchronized 的升级原理,结果挖到了这样一个宝藏图:
其中有一个不解,就是最后的轻量级锁的释放,这里为什么唤醒了其他线程?很多地方锁这里释放失败之后会膨胀为重量级锁?
最后向画这个图的人多学习
大神的博客网址:https://blog.dreamtobe.cn/
博客签名:
I will have a life no remorse, in the future, we must accomplish something.
我将一生没有悔恨,在未来,我们一定要有所成就。
==================================================================
上图好像在偏向锁到轻量级锁的时候少了一步是 owner 指针指向锁对象,不过我想最主要的还是标注的那三步吧。
线程 1 释放的时候,为什么失败的时候,是唤醒被挂起的那些线程?
============================================================================================
因为失败的话,此时锁已经膨胀了。
线程 1 运行的时候,线程 2 进来了,这个时候线程 2 进行 cas 替换指针的时候失败,所以线程 2 自旋操作,达到一定此时已然没有成功,所以线程 2,会导致锁膨胀成重量级锁,而可能自身(线程 2)会被挂起。
线程 1 释放的时候,已经膨胀成重量级锁了,而重量级锁会导致 mark word 指向重量级锁 monitor,改变了锁对象中的 mark word 的值,所以线程 1 释放的时候通过 cas 操作尝试将 Displaced mark word 换回到 object mark word 失败了,所以需要唤醒他们重新在重量级锁中进行竞争。
但是我想,可能存在例外,如果在线程 2 自旋的过程中(还没有到达最大的自旋次数)这个时候没有膨胀成重量级锁,所以这个时候如果线程 1 释放的话,所以是可以释放成功的,而线程 2 也还在自旋,没有被挂起,所以不需要唤醒线程 2
也是想了好久,最后在还是在书中找到了答案。
在《Java 并发编程的艺术》一书中的第 15 页中的–轻量级锁及膨胀流程图,得到了答案
===================================================================
轻量级锁
偏向锁
==============================================================================
其实很简单,原因是为了不想在 lock 与 unlock 这种底层操作上再加同步。
在拷贝完 object mark word 之后,JVM 做了一步交换指针的操作,即流程中第一个橙色矩形框内容所述。
将 object mark word 里的轻量级锁指针指向 lock record 所在的 stack 指针,作用是让其他线程知道,该 object monitor 已被占用。
lock record 里的 owner 指针指向 object mark word 的作用是为了在接下里的运行过程中,识别哪个对象被锁住了。
概括,通过 cas
https://www.bbsmax.com/A/A2dmM7lbde/
到底是两条以上的线程还是两条线程争抢同一个锁会膨胀为重量级锁?
====================================================================================================
之前看博客,多出提到如果有两条以上的线程争用同一个锁,那轻量级锁就不再有效,要膨胀为重量级锁,
,但是上面图片中能够看到命名是两条线程就可以膨胀为重量级锁。
查阅书籍,在《深入理解 Java 虚拟机中》也是这么说我,好吧我猜的没错,像多个博客中写的一模一样的话,大多数都是从书上抄过来的。
如果有两条以上的线程争用同一个锁,那轻量级锁就不再有效,要膨胀为重量级锁,锁标志的状态值变为”10”,Mark Word 中存储的就是指向重量级(互斥量)的指针。
在一篇博文中看到了和我一样的困惑,很多人支持这样的观点,暂时引用过来,当做参考,因为,我确实没有查到其他更好的答案,可能这里确实有歧义吧,暂时不钻牛角尖了。
轻量级锁认为竞争存在,但是竞争的程度很轻,一般两个线程对于同一个锁的操作都会错开,或者说稍微等待一下(自旋),另一个线程就会释放锁。 但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁膨胀为重量级锁,重量级锁使除了拥有锁的线程以外的线程都阻塞,防止 CPU 空转。
原文链接:https://blog.csdn.net/choukekai/article/details/63688332
评论