Java内置锁的核心原理(二)

79 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

引言

上一篇简单介绍了Java内置锁升级的过程,在讲述偏向锁升级为轻量级锁时一笔带过,本文意在通过画图的方式讲解偏向锁的原理。

当存在多个线程竞争同一个锁时,此锁已有偏向,其他线程发现偏向并不是偏向自己,就说明存在了竞争。尝试撤销偏向锁然后膨胀到轻量级锁。

偏向锁的撤销

偏向锁的撤销过程如下:

1.在一个安全点上停止拥有锁的线程

2.遍历线程的栈帧,检查其是否存在锁记录,如果存在锁记录将其清空,并修复存放线程ID的Mark Word,使对象变为无锁的状态。

3.将当前锁升级为轻量级锁,lock位变为00.

4.唤醒当前线程。

偏向锁的膨胀

如果偏向锁已被一个线程占有,其他线程在要占有该锁对象,因为偏向锁不会主动释放,所以JVM会先将偏向锁撤销,撤销后检查之前占有锁的线程是否存活(Mark Word中指向的线程),如果线程挂了,对象变为无锁状态,可重新进行偏向。

如果线程没挂,则膨胀为轻量级锁。

轻量级锁

抢占锁

抢锁线程进入临界区之前,会先在栈帧中创建一个lock record空间,复制一份锁对象的Mark Word保存起来,然后使用CAS(null, lock record地址)函数,将自己的Lock Record地址写到锁对象的Mark Word中,如果写入成功,则该线程占有轻量级锁成功,owner指向对象的地址。如写入失败,则循环尝试CAS。

image-20211123235916328