并发编程学习笔记-锁的膨胀升级

基础知识

实例对象的结构如下
并发编程学习笔记-锁的膨胀升级_第1张图片
以32位的JVM为例子,Mark World的组成成分如下:
并发编程学习笔记-锁的膨胀升级_第2张图片

轻量级锁的使用场景

JDK 1.6之后对Synchronized进行了优化,如自旋锁,偏向锁和轻量级锁,并且默认开启了偏向锁,相关指令如下:
在这里插入图片描述
并发编程学习笔记-锁的膨胀升级_第3张图片自适应自旋是指根据上一次自选次数而弹性的分析设置自旋次数,JDK1.7之后才有的这种情况,在JDK1.7之前需要自己设置自旋的次数,这样会造成效率低下。

锁的升级路线

并发编程学习笔记-锁的膨胀升级_第4张图片

锁的升级总图

无锁升级到轻量级锁

并发编程学习笔记-锁的膨胀升级_第5张图片

解释

1、线程1最开始处于无锁状态,在访问同步块的时候,先是检查实例的最后两位,确定为偏向锁或者无所,在检查倒数第三位,判断为无锁状态,这时,CAS方法修改实例的Mark Word,获取到偏向锁。Mark Word的修改内容:前25位中23位变为线程的ID,后两位变为Epoch;同时将倒数第3位改为1。
2、观看图中第二部分,可以看到线程2也准备访问同步块,这时检查实例对象中的偏向线程ID是否是自己,如果不是自己,CAS准备修改线程ID位自己的线程ID,肯定会修改失败,这时,开始向JVM申请撤销偏向锁,线程1在到达安全点后暂停线程,如果这时线程1已经运行出了同步块,那么MarkWord变为无锁状态,线程2还是通过CAS来获取偏向锁。

无锁升级到重量级锁

并发编程学习笔记-锁的膨胀升级_第6张图片

解释

1、首先对象的实例在堆中,且加锁的对象是同一个,因此Object MarkWord是可以被双方访问的,观察图中中间的
并发编程学习笔记-锁的膨胀升级_第7张图片
这个对象头指的就是堆中的对象实例
2、轻量级锁的结构如下:
并发编程学习笔记-锁的膨胀升级_第8张图片
右边的对象头指的是堆中的实例对象的对象头,而不是线程栈中LockRecord空间

3、线程2的第一次修改失败后进入自旋,其中自旋失败指的是超出了JVM自适应的自旋次数,以LINUX为例,调用了内核中的Phtead包中的mutex_lock指令,其中状态转换耗时高,资源消耗多,操作多,在图中位置如下:
并发编程学习笔记-锁的膨胀升级_第9张图片

你可能感兴趣的:(并发编程学习笔记-锁的膨胀升级)