1.锁升级的4种状态:
无锁状态
四川中医药大学偏向锁状态
轻量级锁状态
重量级锁状态
2.整体的流程图
3.详细介绍
偏向锁状态
原因:
大多数时候是不存在锁竞争的,常常是一个线程多次获得同一个淮中晚泊犊头锁,因此如果每次都要竞争锁会增大很多没有必要付出的代价,为了降低获取锁的代价,才引入的偏向锁。
升级:
当线程1访问代码块并获取锁对象时,会在java对象头和栈帧中记录偏向的锁的threadid,因为偏向锁不会主动释放锁,因此以后线程1再次获取锁的时候,需要比较当前线程的threadid和java对象头中的threadid是否一致,如果一致(还是线程1获取锁对象),则无需使用cas来加锁、解锁;
如果不一致,那么需要查看java对象头中记录的线程1是否存活,如果没有存活,那么锁对象被重置为无锁状态,其它线程(线程2)可以竞争将其设置为偏向锁;
如果存活,那么立刻查找该线程(线程1)的栈帧信息,如果还是需要继续持有这个锁对象,那么暂停当前线程1,撤销偏向锁,升级为里屋轻量级锁,如果线程1不再使用该锁对象,那么将锁对象状态设为无锁状态,重新偏向新的线程。
轻量级锁状态
原因:
轻量级锁考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景。因为阻塞线程需要cpu从用户态转到内核态,代价较大,如果刚刚阻塞不久这个锁就被释放了,那这个代价就有点得不偿失了,因此这个时候就干脆不阻塞这个线程,让它自旋这等待锁释放。
升级:
线程1获取轻量级锁时会先把锁对象的对象头markword复制一份到线程1的栈帧中创建的用于存储锁记录的空间(称为displacedmarkword),然后使用cas把对象头中鼓励孩子的寄语的内容替换为线程1存储的锁记录(displacedmarkword)的地址;
如果在线程1复制对象头的同时(在线程1cas之前),线程2也准备获取锁,复制了对象头到线程2的锁记录空间中,但是在线程2cas的时候,发现线程1已经把对象头换了,线程2的cas失败,那么线程2就尝试使用自旋锁来等待线程1释放锁。
但是如果自旋的时间太长也不行,因为自旋是要消耗cpu的,因此自旋的次数是有限制的,比如10次或者100次,如果自旋次数到了线程1还没有释放锁,或者线程1还在执行,线程2还在自旋等待,这时又有一个线程3过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止cpu空转。
4.对象头布局
对象头:比如 hash码,对象所属的年代,对象锁,锁状态标志,偏向锁(线程)id,偏向时间,数组长度(数组对象)等
实例数据:即创建对象时,对象中成员变量,方法等
对齐填充:对象的大小必须是8字节的整数倍
mark word
以32位jvm中存储内容为例:
锁状态25 bit4bit1bit2bit锁标志位是否是偏向锁23bit2bitgc标记空11重量级锁指向重量级锁monitor的指针(依赖mutex操作系统的互斥)10轻量级锁指向线程栈中锁记录的指针pointer to lock reco上学歌一年级rd00偏向锁线程idepoch对象分代年龄101无锁对象的hashcode对象分代年龄001补充:这里的例子是32位系统,不同位数的系统对象头略有不同
本文发布于:2023-04-05 04:17:19,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/eb1cbf4950974cbcb19481c4b3ab3271.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:java怎么升级系统框架(简单的java程序代码).doc
本文 PDF 下载地址:java怎么升级系统框架(简单的java程序代码).pdf
留言与评论(共有 0 条评论) |