synchronized锁的膨胀过程流程图
2020-04-02 14:04:37 1 举报
synchronized锁从无锁、偏向锁、轻量级锁、重量级锁的膨胀过程.
作者其他创作
大纲/内容
0 0(轻量级锁)
未存活
a 对象正在偏向的线程的 线程栈
unused | hashcode | unused | age | 0 0 1
Lock Record point address | 0 0
撤销为无锁状态
挂起 t1 线程
指向 a 对象的 MarkWord地址的指针地址
失败
执行同步代码块
000000(Displaced Mark Word)
CAS是否成功
如果一致,说明 a 已经偏向了该线程也就是t1线程,那么 t1 线程栈中应该已经有至少一条 Lock Record记录所以这里只需要生成一个Displaced Mark Word为空的Lock Record对象,放入T1 线程栈
插入线程栈
存活
结束释放锁a 变为 001 无锁状态
a 锁偏向的线程
结束释放锁此时 a 的状态应该是一个重量级锁唤醒被挂起的线程
1 0(重量级锁锁)
将 a 锁升级为重量级锁
撤销为无锁
通过遍历线程栈中的Lock Record记录来判断是否在执行同步代码块
unused | hashcode | unused | age | 001
a此时为 001状态(无锁)
T1线程执行synchronized (a)
成功
根据 a 的对象头判断
lock record point | 00
其他信息
lock Record 指向的是线程栈的内容
当前的t1线程
非001状态
T1 的线程ID和 a 对象MarkWord中记录的Thread ID是否一致
在执行同步代码块
CAS操作尝试将 lock record 对象的stack指针地址写入 a 对象的MarkWord中,CAS 期望值是 lock record 中之前拷贝的 a 对象的 MarkWord内容CAS可以成功,说明a对象还没被其他线程锁定CAS失败,说明a对象被其他线程抢先一步锁定了
101(偏向锁)
Thread ID | epoch | unused | age | 1 0 1
a 对象
继续执行
至此,a锁已经升级为轻量级锁接下来分两步1、唤醒 a 锁偏向的线程2、继续执行当前的 t1 线程
获得偏向锁生成一个 Lock Record 对象,保存到 T1的线程栈中a 对象的MarkWord变为T1 的Thread ID | epoch | unused | age | 1 0 1
判断自旋次数好像是10次
自旋
获取锁失败
结束
lock record
唤醒 a 锁对象之前偏向的线程
new 一个lock Record对象然后放入 偏向线程的线程栈中
T1 线程栈
暂停 a 对象MarkWord中记录的 Thread ID的线程也就是暂停 a 对象锁偏向的那个线程
继续执行同步代码块里的代码
未执行同步代码块
a此时为 001状态(偏向锁)
将生成的lock Record插入 t1 线程栈
升级到轻量级锁new 一个Lock Record 对象,将 a 对象MarkWord 拷贝到 Lock Record对象的Displace Mark Word,然后放入 偏向线程的线程栈中然后修改 a 锁对象的MarkWord内容为生成lockRecord对象的地址
开始撤销偏向锁
Thread ID | epoch | unused | age | 1 0 1(拷贝 a 对象的MarkWord存到这,这里叫Displaced Mark Word)
001状态
对象 a是否为001无锁状态
达到阈值
执行CAS操作抢占偏向锁CAS的预期值是:a 对象MarkWord的Thread ID为0000是才能成功CAS写入值是:将 t1 的Thread ID写入 a 对象的MarkWord中
执行代码块
线程是否在执行同步代码块中的代码
未达到阈值
X Thread ID | epoch | unused | age | 1 0 1
这里指针指向的就是 t1线程栈里的 lock record的地址
等待全局安全点
获取锁成功a 对象的MarkWord 存入 t1 线程的 lock record地址
0 0 1(无锁)
判断a对象锁偏向的线程的状态
这里指针指向的是 a 对象的 MarkWord 的地址
CAS成功的话
轻量级解锁这里也是通过CAS操作比较的是 lock record的地址 和 a 对象MarkWord中的是否一致写入的就是 将 a 恢复为 001 无锁状态
一致
依次删除对应Lock Record但是不修改 对象 a 的MarkWord内容
当前的 t1 线程
生成一个 Lock Record 对象,保存到 T1的线程栈中
CAS操作失败说明 a 对象中MarkWord部分和t1线程中的 lock record 记录不一致,也就说明了 在t1执行同步代码块这段时间由其他线程尝试获取过锁,从而导致锁升级了,变成了重量级锁,MarkWord修改为了指向monitor的地址。尝试获取锁的那个线程会被挂起
CAS操作成功说明 a 对象的MarkWord和线程t1中的 lockrecord记录一致,也就说明 在 线程 t1 执行 同步代码块这段时间,没有其他线程尝试获取过锁,也就是没有竞争。锁没有被升级为重量级锁。
unused | hashcode | unused | age | 001(拷贝 a 对象的MarkWord,存到这里)
唤醒 a锁对象之前偏向的那个线程也就是现在获取轻量级锁的线程
不一致
0 条评论
下一页