从 Bytecodes 探讨 Synchronized 锁优化
2024-01-26 09:20:35
从字节码出发定位到 monitorenter/monitorexit
从 Java 的编译过程来看,编译后的代码文件为 class 文件,class 文件是字节码。字节码是一种二进制代码,它可以用字节码指令集来执行。Java 虚拟机 (JVM) 就是一个字节码解释器,它可以执行字节码指令集。
synchronized 在编译成字节码时,会被编译成 monitorenter 和 monitorexit 这两条字节码指令。monitorenter 指令表示进入同步块,monitorexit 指令表示退出同步块。
从 HotSpot 源码中 monitorenter 和 monitorexit 部分源码中抽丝剥茧带你理解 synchronized
HotSpot 是 Java 虚拟机的实现之一,它是由 Sun Microsystems 开发的。HotSpot 源码是开源的,我们可以从 HotSpot 源码中了解到 synchronized 的实现细节。
monitorenter 和 monitorexit 这两条字节码指令在 HotSpot 源码中分别对应着 ObjectMonitor 类中的 enter 和 exit 方法。ObjectMonitor 类是一个抽象类,它定义了同步监视器的基本行为。
synchronized 关键字的实现主要依赖于 Java 对象头中的 markword 字段。markword 字段是一个 64 位的字段,它存储了对象的状态信息,包括锁的状态。
当一个线程进入同步块时,它会尝试获取对象的锁。如果对象锁没有被其他线程持有,那么该线程就会获取对象的锁,并将对象的 markword 字段设置为指向自己线程的指针。
当一个线程退出同步块时,它会释放对象的锁,并将对象的 markword 字段设置为 null。
synchronized 锁优化
HotSpot 虚拟机对 synchronized 进行了很多优化,这些优化主要包括:
- 偏向锁: 当一个对象被同一个线程多次锁定时,HotSpot 虚拟机会将该对象标记为偏向锁。偏向锁是一种轻量级的锁,它不需要使用 CAS 指令来获取锁。
- 轻量级锁: 当一个对象被多个线程竞争时,HotSpot 虚拟机会将该对象标记为轻量级锁。轻量级锁是一种比偏向锁更重一些的锁,它需要使用 CAS 指令来获取锁。
- 重量级锁: 当一个对象被多个线程激烈的竞争时,HotSpot 虚拟机会将该对象标记为重量级锁。重量级锁是一种最重的锁,它需要使用 synchronized 关键字来获取锁。
HotSpot 虚拟机会根据对象的竞争情况来动态地调整对象的锁类型,从而提高程序的性能。
总结
synchronized 是 Java 中的一个非常重要的锁机制,它可以保证多个线程对共享资源的访问是同步的。HotSpot 虚拟机对 synchronized 进行了很多优化,这些优化主要包括偏向锁、轻量级锁和重量级锁。HotSpot 虚拟机会根据对象的竞争情况来动态地调整对象的锁类型,从而提高程序的性能。