synchronized 在 java 底层通过对象关联的 monitor 实现,monitor 由 jvm 封装操作系统原语(mutex、condition variable)构建,含 owner、entrylist 和 waitset;编译为 monitorenter/monitorexit 指令,支持偏向锁、轻量级锁和重量级锁三级优化。

synchronized 在 Java 底层是通过对象的 Monitor(监视器锁) 实现的,而 Monitor 本身由 JVM 基于操作系统原语(如互斥量 mutex、条件变量 condition variable)封装而成,并与每个 Java 对象关联。
每个对象都有一把内置 Monitor 锁
Java 中每个对象(包括数组)在创建时,JVM 都会为其分配一个与之绑定的 Monitor 结构。这个结构并不直接暴露给开发者,而是通过字节码指令和运行时系统协同管理。
- Monitor 包含三个核心部分:一个 owner(持有线程)、一个 EntryList(等待获取锁的线程队列)、一个 WaitSet(调用 wait() 后挂起的线程队列)
- 当线程执行
synchronized(obj)或同步实例方法时,实际是在尝试获取obj关联的 Monitor 的所有权 - 如果 Monitor 未被占用(owner 为 null),当前线程直接成为 owner;否则进入 EntryList 等待唤醒
字节码层面:monitorenter 和 monitorexit
编译后的 synchronized 代码会被编译器转换为一对字节码指令:
-
monitorenter:在进入同步块/方法前执行,尝试获取对象的 Monitor 锁 -
monitorexit:在退出同步块/方法后执行,释放 Monitor 锁 - JVM 保证即使发生异常,也会通过异常表插入隐式的
monitorexit,确保锁一定被释放
Monitor 的实现依赖操作系统原语
JVM(如 HotSpot)中的 Monitor 是 C++ 实现的 ObjectMonitor 类,其内部使用:
- 一个
mutex(互斥量)保护 Monitor 自身状态的并发访问 - 一个或多个
condition variable(如_WaitSetLock、_cxq等)用于线程挂起与唤醒 - 线程竞争锁失败时,会先自旋(spin),失败后再阻塞(park),避免频繁用户态/内核态切换
偏向锁、轻量级锁、重量级锁是 Monitor 的优化形态
HotSpot 并非每次都直接用重量级操作系统锁。它根据竞争程度动态升级:
- 偏向锁:无竞争时,将锁偏向第一个线程,只记录 thread ID,几乎零开销
- 轻量级锁:有轻微竞争,用 CAS 尝试将对象头 Mark Word 替换为指向栈中 Lock Record 的指针
- 重量级锁:竞争激烈时,膨胀为真正的 Monitor 锁,线程进入操作系统等待队列
- 这些状态都服务于同一个目标:高效地协调 Monitor 的 owner 切换和线程调度
不复杂但容易忽略:synchronized 的“锁”本质不是关键字本身,而是对象头里的 Mark Word 和与之绑定的 Monitor 实例——前者记录锁状态,后者提供同步语义的底层支撑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











