Java对象锁本质是JVM对操作系统管程思想的封装,依赖对象头Mark Word状态(01/00/10)动态关联轻量级锁、偏向锁或堆中Monitor实例,仅重量级锁才真正触发futex系统调用实现阻塞唤醒。

Java 中的对象锁本质上是 JVM 层面对操作系统管程(Monitor)模型的封装实现,不是直接调用操作系统的管程原语,而是基于其思想、结合 Java 对象结构与 JVM 运行时机制构建的一套同步体系。
对象锁依赖 Monitor,而 Monitor 是 JVM 管理的逻辑结构
每个 Java 对象在运行时都关联一个 Monitor(监视器),但它并非一开始就存在。只有当线程首次对该对象执行 synchronized 操作时,JVM 才可能为其创建或复用 Monitor 实例。这个 Monitor 并非操作系统内核中的“管程”实体,而是 JVM 在堆内存中维护的一个数据结构,包含 Owner、EntryList、WaitSet 等字段,用于模拟 Mesa 管程模型的行为。
Monitor 的核心作用是:
- 记录当前持有锁的线程(Owner)
- 管理竞争锁但未获取到的线程队列(EntryList)
- 存放因调用 wait() 而释放锁并挂起的线程(WaitSet)
锁状态变化映射到对象头 Mark Word
Java 对象头中的 Mark Word 是轻量级锁、偏向锁和重量级锁状态切换的关键载体:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 无锁状态:Mark Word 存储哈希码、GC 分代年龄等信息(末两位为 01)
- 偏向锁:记录偏向线程 ID 和 epoch(末两位仍为 01,但 biased_lock=1)
- 轻量级锁:指向当前线程栈帧中 Lock Record 的指针(末两位为 00)
- 重量级锁:指向堆中 Monitor 对象的指针(末两位为 10)
只有升级到重量级锁时,Monitor 才真正被实例化,且此时 Mark Word 才会存储其地址。也就是说,对象锁是否“关联 Monitor”,取决于锁的级别,而非对象本身是否声明为 synchronized。
操作系统层面的最终落地靠 futex 或 Mutex
当 Monitor 进入重量级锁阶段,JVM 需要借助操作系统能力阻塞/唤醒线程。在 Linux 上,它通过 futex(Fast Userspace Mutex)系统调用实现:
- 线程尝试获取锁失败 → 调用 futex_wait 进入内核等待队列
- 持有锁线程释放锁 → 调用 futex_wake 唤醒等待线程
这一过程涉及用户态到内核态的切换、上下文保存与恢复,开销较大——这也是 JVM 引入偏向锁、轻量级锁等优化的原因:尽量避免走到这一步。
synchronized 与管程通信机制的对应关系
Java 的 wait()/notify()/notifyAll() 方法,正是管程中“条件变量(Condition Variable)”的体现:
- wait():当前线程释放 Monitor 所有权,进入 WaitSet,并让出 CPU
- notify():从 WaitSet 中随机唤醒一个线程,使其重新进入 EntryList 竞争锁
- notifyAll():唤醒 WaitSet 中所有线程
注意:这些操作必须在已持有该对象 Monitor 的前提下才能调用(即必须在 synchronized 块内),否则抛出 IllegalMonitorStateException。这也印证了 Java 管程的“互斥 + 条件等待”双重契约。

















