在说轻量级锁的CAS操作之前先说一下CAS操作的实现,CAS(compare and swap)比较和替换,它里面有三个值,当前
原值,预期原值和目的值,只有当当前原值和预期原值还保持一样的时候才会将当前原值替换为目的值。
而在轻量级锁里面,我们先知道,轻量级锁所对应的实际环境是交替执行的线程获取锁,并不会发生竞争,理解清楚这一点
很重要,所以这里的CAS中mark word中轻量级pointer的预期原值是什么,是null,而目的值则是自己,要将那个mark word
的pointer修改为指向自己,而当前原值,也就是只有在pointer是null的时候也就是没有线程获取对象锁。才能够使CAS操作成
功。如果失败,一种情况是该线程持有该锁,一看pointer是指向自己那无所谓,继续执行同步块,另一种情况不是指向自
己,那不好意思发生了竞争,反手我就膨胀成重量级锁。于是这又让后面的轻量级锁的解锁过程CAS有了用武之地。
刚刚是加锁过程,然后到了解锁的时候,这时候线程我要解锁了,解锁过程就是将先前复制锁对象的mark word又给替换回
去。这里你们想到什么了,由于已经膨胀成了重量级锁,mark word已经发生了改变,当前原值和预期原值又不一样了。解锁
失败,当然后续依然会释放这个锁,有这么个解锁过程是为了在失败时候知道有另外一个线程竞争过这个锁,而且被挂起了。
下面将轻量级的整个加锁过程梳理一下:
(1)虚拟机首先在当前栈帧中建立一个名为锁记录(lock Record)的空间用于存放mark word的拷贝,这其实就是用于后面解锁过程使用CAS操作的。
(2)使用CAS操作将对象mark word更新为指向自己的指针。
(3)更新成功,那么线程就拥有该锁了。
(4)更新失败,要么就是上面说的已经指向了自己。要么就是指向了别人,指向别人我就膨胀。
解锁过程
(1)将mark word 复制回去,复制成功,释放该锁,也就完成了整个操作同步数据的流程
(2)复制失败,正面mark word已经在膨胀为重量级的路上越走越远。那还是释放掉这个锁,顺便多一道唤醒挂起线程的操作