synchronized通过Monitor实现线程安全,同步代码块用monitorenter/monitorexit指令,同步方法靠ACC_SYNCHRONIZED标志。每个对象的对象头中Mark Word记录锁状态和线程信息,支持偏向锁(单线程无CAS)、轻量级锁(CAS竞争)到重量级锁(操作系统互斥量)的升级,不可降级。wait/notify基于Monitor的等待队列实现线程协作,整体通过JVM优化在低竞争下高效、高竞争下正确。

在 Java 中,synchronized 是用来保证线程安全的关键字,它的底层实现依赖于 JVM 对对象监视器(Monitor)的支持。synchronized 的实现主要基于对象头中的 Mark Word 和操作系统的互斥锁(Mutex Lock)机制。
1. synchronized 作用于代码块和方法的底层差异
synchronized 可以修饰代码块或方法,其底层实现略有不同:
- 同步代码块:通过 monitorenter 和 monitorexit 指令实现。JVM 在编译后会在同步块前后插入这两个指令,进入时获取 Monitor 锁,退出时释放。
- 同步方法:通过方法访问标志中的 ACC_SYNCHRONIZED 标志实现。当方法被调用时,JVM 会检查该标志,若有,则先尝试获取 Monitor,执行完后再释放。
2. Monitor(监视器)与对象头的关系
每个 Java 对象都可以作为锁,是因为每个对象在堆中都有一个对象头(Object Header),其中包含一个叫 Mark Word 的结构。Mark Word 在 64 位 JVM 中通常记录:
当某个线程进入 synchronized 块时,JVM 会检查对象的 Mark Word 状态,根据当前情况决定是否升级锁。
立即学习“Java免费学习笔记(深入)”;
3. 锁的升级过程(偏向锁 → 轻量级锁 → 重量级锁)
为了减少获取锁的开销,synchronized 实现了锁的优化策略,包括以下几种状态:
- 无锁状态:对象未被任何线程锁定。
- 偏向锁:适用于只有一个线程反复进入同步块的情况。第一次获取锁时,线程 ID 被记录在 Mark Word 中,之后该线程再进入无需 CAS 操作。
- 轻量级锁:当有第二个线程竞争时,偏向锁升级为轻量级锁。线程在自己的栈帧中建立锁记录(Lock Record),通过 CAS 将对象的 Mark Word 替换为指向锁记录的指针。
- 重量级锁:当竞争加剧(如多个线程自旋等待失败),JVM 将锁升级为重量级锁,此时依赖操作系统层面的互斥量(mutex),线程会进入阻塞状态,性能开销大。
锁只能升级不能降级,这是为了保证效率和安全性。
4. wait/notify 与 Monitor 的关系
Monitor 不仅用于互斥,还支持线程间的协作。当线程调用 wait() 方法时,它会释放 Monitor 并进入 Monitor 的等待队列;其他线程调用 notify() 或 notifyAll() 时,会唤醒等待队列中的线程重新竞争锁。
基本上就这些。synchronized 的高效之处在于 JVM 层面结合了对象头、CAS 操作和操作系统锁的综合优化,从偏向锁到重量级锁的动态升级机制,使得它在低竞争下性能很好,在高竞争下也能保证正确性。











