深入理解synchronized
- 管程synchronized
- 对象的内存布局
- 锁状态记录
- 锁对象状态转换
- 偏向锁
- 轻量级锁
- 锁对象转换总结
管程synchronized
Java 参考了 MESA 模型,语言内置的管程(synchronized)对 MESA 模型进行了精简。
对象的内存布局
- 对象头
- MarkWord(记有锁标记) 8字节
- 压缩指针 4字节
- 实例数据 (xx)字节
- 对齐填充 8的整倍数
使用JOL工具查看内存布局
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.4</version>
</dependency>
锁状态记录
锁对象状态转换
偏向锁
-
偏向锁延迟机制:HotSpot 虚拟机在启动后有个
4s
的延迟才会对每个新建的对象开启偏向锁模式。JVM启动时会进行一系列的复杂活动,比如装载配置,系统类初始化等等。在这个过程中会使用大量synchronized关键字对对象加锁,且这些锁大多数都不是偏向锁。为了减少初始化时间,JVM默认延时加载偏向锁。 -
偏向锁撤销之调用对象HashCode
偏向锁无法储存HashCode
1.调用HashCode,偏向锁变为无锁态
//jvm延迟偏向 Thread.sleep(5000); Object obj = new Test(); obj.hashCode(); //查看对象内部信息 System.out.println(ClassLayout.parseInstance(obj).toPrintable());
2.调用HashCode,偏向锁将升级成重量锁
new Thread(()->{ synchronized (obj){ obj.hashCode(); System.out.println(Thread.currentThread().getName()+"\n"+ClassLayout.parseInstance(obj).toPrintable()); } },"Thread2").start();
-
偏向锁撤销之调用wait/notify
偏向锁状态执行obj.notify() 会升级为轻量级锁
,
偏向锁状态执行obj.wait(timeout) 会升级为重量级锁
轻量级锁
轻量级锁: 两个线程轻微竞争
偏向锁升级轻量级锁
轻量级锁膨胀为重量级锁,过程为:轻量级锁 --》无锁态 --》 重量级锁
锁对象转换总结
简单理解:锁升级时都会先变为无锁状态,然后升级为其他锁状态
无锁态
--》偏向锁 -》轻量级锁 -》无锁态
-》 重量级锁