synchronized 关键字详解
synchronized 是 Java 内置的互斥锁,基于 monitor 实现。理解其底层原理对于编写高效的并发代码至关重要。我们可以从字节码、JVM 内存结构以及硬件层面来层层剖析。
1. 字节码层面:monitorenter 和 monitorexit
当编译器处理 synchronized 关键字时,无论是修饰代码块还是方法,都会生成对应的字节码指令。
同步代码块
对于 synchronized(object) { ... },编译器会在同步代码块的前后分别生成 monitorenter 和 monitorexit 指令。值得注意的是,为了应对异常,编译器会生成两个 monitorexit 指令:一个用于正常退出,另一个隐藏在 finally 语义中,确保即使同步块内抛出异常,锁也能被正确释放。
编译后的字节码大致如下:
public void method(); Code:
0: aload_0
1: getfield #2 // 获取对象引用 obj
4: dup
5: astore_1
6: monitorenter // 进入同步块,尝试获取锁
7: getstatic #3 // 获取 System.out
10: ldc #4 // 加载 "hello"
12: invokevirtual #5 // 调用 println
15: aload_1
16: monitorexit // 正常退出同步块,释放锁
17: goto 25
20: astore_2
21: aload_1
22: monitorexit // 异常退出同步块,释放锁 (确保在异常情况下也能释放锁)
23: aload_2
24: athrow
25: return
同步方法
对于 synchronized 修饰的方法,方法常量池中会设置 ACC_SYNCHRONIZED 标志。当方法调用时,执行线程会先尝试获取锁(实例方法是 ,静态方法是类对象),再执行方法体。方法执行完毕后,无论正常返回还是异常抛出,都会自动释放锁。






