Java synchronized 关键字详解:从字节码到对象头与锁升级
synchronized 是 Java 内置的互斥锁机制,底层基于 Monitor 实现。其核心原理涉及字节码指令、JVM 对象头状态管理以及硬件层面的 CAS 与内存屏障。
synchronized 底层原理(总结版)
synchronized 底层使用的是 Monitor,Monitor 被翻译为监视器,是由 JVM 提供,C++ 语言实现。
使用 javap -v xxx.class 反编译一段代码可以看到机器指令:
monitorenter:上锁开始的地方monitorexit:解锁的地方- 其中被
monitorenter和monitorexit包围住的指令就是上锁的代码 - 第二个
monitorexit是为了防止锁住的代码抛异常后不能及时释放锁
Monitor 内部具体的存储结构:
- Owner:存储当前获取锁的线程,只能有一个线程可以获取
- EntryList:关联没有抢到锁的线程,处于 Blocked 状态的线程
- WaitSet:关联调用了 wait 方法的线程,处于 Waiting 状态的线程
具体的流程:
- 进入 synchronized 代码块时,先让 lock(对象锁)关联 monitor,然后判断 Owner 是否有线程持有
- 如果没有线程持有,则让当前线程持有,表示该线程获取锁成功
- 如果有线程持有,则让当前线程进入 EntryList 进行阻塞,如果 Owner 持有的线程已经释放了锁,在 EntryList 中的线程去竞争锁的持有权(非公平)
- 如果代码块中调用了 wait() 方法,则会进去 WaitSet 中进行等待
synchronized 底层原理(详解版)
synchronized 的底层原理可以从三个层面来看:字节码层面、JVM 底层实现 和 硬件层面。
1. 字节码层面:monitorenter 和 monitorexit
当我们使用 synchronized 关键字时,无论是修饰代码块还是方法,在编译后的字节码中都会生成对应的指令。
同步代码块
对于 synchronized(object) { ... },编译器会在同步代码块的前后分别生成 monitorenter 和 monitorexit 指令。
public void method() {
synchronized(obj) {
// 同步代码块
System.out.println("hello");
}
}
编译后的字节码大致如下:
public void method(); Code:
0:


