详解Synchroniezd锁升级机制

137 阅读3分钟

每个线程的栈帧中会有一个保存对象头中mark work的锁记录结构

锁的升级和降级主要通过对象头(Object Header)中的锁标志位和相关数据结构实现.·对象头(Object Header) :包含锁标志位和其他锁相关信息。

Mark Word:对象头的一部分,用于存储锁信息。根据锁的状态,Mark Word 中的内容会有所不同。以下是对象头中Mark Word 的不同状态:

1.无锁状态: Mark Word中包含对象的哈希码(HashCode)等信息。

2偏向锁状态:Mark Word 中包含偏向线程的ID.

3轻量级锁状态: Mark Word 中包含指向栈中锁记录(Lock Record)的指针。

4重量级锁状态: Mark Word中包含指向重量级锁(monitor)的指针。


轻量级锁:在多线程的环境下,各个线程在不同的时间段进行加锁的操作,无竞争

加锁操作:

1.将Markword复制到自己栈帧中锁记录结果

2.通过CAS操作对markword进行修改,添加自己的锁记录地址

3.执行同步代码块

4.如果发生重入

    1.线程锁记录结构拉取Markword

    2.首先cas操作会失败,发现是自己锁

    3.锁重入

    4.执行同步代码

    5.执行完毕,栈帧弹出一条Mark记录

5.执行完毕,栈帧弹出一条Mark记录

6.解锁,Cas操作Mark会变为无锁状态,01

锁膨胀:当CASMarkWord的时候失败了,说明锁正在被其他线程占用,就会发生锁膨胀

加锁操作

1.将Markword复制到自己栈帧中锁记录结果

2.通过CAS操作对markword进行修改

3.CAS失败,发现被别的线程占用

4.CASMark为重量级锁

5.阻塞

    1.占有锁的线程解锁失败(CASMark失败)

    2.释放重量级锁,唤醒同步队列中的线程进行锁竞争

    6.其他线程释放锁,开始竞争锁

6.解锁,Mark会变为无锁状态,01

重量级锁:通过MonitorEnter、MonitorExit来进入锁、释放锁;优化上增加了锁自旋

锁自旋

1.将Markword复制到自己栈帧中锁记录结果

2.通过CAS操作对markword进行修改

3.CAS失败,发现被别的线程占用

4.CASMark为重量级锁

5.不断地自旋重试

    1.重试成功后,获取锁,避免了一系列阻塞操作

    2.重试失败后,阻塞

6.其他线程释放锁,开始竞争锁

6.解锁,Mark会变为无锁状态,01

偏向锁:轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行CAS操作。Java 6中引入了偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS.

1.将Markword复制到自己栈帧中锁记录结果

2.通过CAS操作对markword进行修改,添加自己的线程ID

3.执行同步代码块

4.如果发生重入

    1.将Markword复制到自己栈帧中锁记录结果

    2.对象头中ID为自己的ID

    3.锁重入

    4.执行同步代码

5.执行完毕,栈帧弹出一条Mark记录

5.执行完毕,栈帧弹出一条Mark记录

6.解锁,Cas操作Mark会变为无锁状态,01