synchronized锁升级过程精简理解

首先锁升级的过程:无锁->偏向锁->轻量级锁->重量级锁

使用实际案例举例子,来帮助大家理解:

我们要共享obj对象,加入现在只有一个线程A,线程id为10,此时它在执行前观察一下obj对象头中占用它的线程id是不是没有(也就是没人占用这个锁),如果是,则使用CAS将它改为10,当A执行完后看看现在obj中是不是10,如果是则表示没人跟我抢锁,我刚刚的执行有效,这就是偏向锁。

此时又来了一个线程B,线程id为20,还是上方一样A在执行使用CAS将obj对象头中线程id改为10,A继续执行了,B此时来了,它观察obj是偏向锁的状态,且对象头中有线程id且不为20,此时锁需要膨胀为轻量级锁,同时获取偏向锁的线程被挂起。

在轻量级锁的状态时,每个线程都会在栈帧中开辟一块锁记录空间(Lock Record),每次执行前先将对象头中mark word中信息copy进来,然后使用CAS尝试将mark word指针指向本线程的Lock record,如果成功则成功,否则说明期间被其他线程修改,他需要自旋转,也就是再执行,若自旋到达一定次数的时候,膨胀为重量级锁。

重量级锁也就是需要获取对象的monitor,字节码会在synchronized前后生成monitorenter与monitorexit,标识获取或者释放这个监视器锁(monitor)。

无锁:在未执行代码的时候,不会对对象加锁

经过上方形象的例子可以看出来,只要没膨胀为重量级锁,我们都没有进入到内核态,性能还是很高的哈 ,但是如果长时间的自旋,cpu占用可能也会很大。

推荐一个博主讲的,觉得写得很好,如果只是精简理解下过程,看我最上方的例子想必也都能明白了: https://blog.csdn.net/Javazhoumou/article/details/98866734

原文地址:https://www.cnblogs.com/ningxinjie/p/13646884.html