synchronized的锁膨胀

又继续说这个锁了。

对于jdk1.6之后的synchronized关键字,不再是以前完全基于mutex的重量级锁。而是加入了一些优化。

使用对象头的Mark Word的锁标记位进行控制。

锁的概念是针对于线程的。只是针对于线程的!针对于线程的!!!

所以实现锁,或者说,锁的状态,也是对于线程而言的。但是加锁需要一个媒介,也就是加锁的对象。那么对这个对象成功加锁怎么表示呢?

对象分为三部分,对象头,数据,填充位。对于对象的控制就是在对象头实现的。其中有两位作为锁位。标记了当前的锁状态。

1、当一个线程进入同步方法块的时候,虚拟机首先会在它的栈帧上建立一个名叫lock Record的空间,用于储存锁对象当前的mark Word的拷贝。

2、将对象头的Mark Word拷贝到线程的锁记录(Lock Recored)中。

3、拷贝成功后,虚拟机将使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针,并更新锁位为偏向锁。(指针指向了线程的lock Record,里面存的数据是对象头的,所以从结构上来说,是合理的)。

4、当有新的线程进入同步块的时候,检查Mark Word中的指针,如果是当前线程,那么直接放行,如果不是,那么线程开始自旋重新获取锁,并且更新锁位为轻量级锁。

5、如果自旋一段时间之后,还是拿不到,就把Mark Word更新为指向Monitor的指针,并更新为重量级锁。

销毁就是释放锁,把对象的东西换给它。

参考资料

对象头:https://blog.csdn.net/zhxin606a/article/details/88399283

原文地址:https://www.cnblogs.com/hekiraku/p/12332145.html