Java中synchronized的隐式锁依赖对象头Mark Word复用存储空间编码锁状态,通过低2–3位标志位(01/00/10/11)区分无锁、偏向锁、轻量级锁、重量级锁及GC状态,并在锁升级过程中动态修改Mark Word内容,最终重量级锁指向C++堆中的ObjectMonitor对象。

Java 中 synchronized 使用的隐式锁(也称监视器锁、monitor lock)底层依赖对象头中的 Mark Word 来记录锁状态,而不是额外分配锁对象。JVM 通过在 Mark Word 中复用存储空间,以少量比特位编码不同锁状态,实现轻量级、高效、无侵入的同步机制。
Mark Word 的结构与锁状态位布局
在 HotSpot 虚拟机中,每个 Java 对象头包含两部分:Mark Word 和 Class Pointer(类型指针)。其中 Mark Word(通常 64 位,在 32 位 JVM 或开启压缩指针时可能为 32 位)是锁信息的核心载体。它并非固定存“锁”,而是根据对象当前状态动态复用字段:
- 未锁定状态:存储哈希码、分代年龄、是否偏向锁等信息
- 偏向锁状态:存储偏向线程 ID、偏向时间戳、epoch 等
- 轻量级锁状态:存储指向当前线程栈中 Lock Record 的指针
- 重量级锁状态:存储指向操作系统互斥量(mutex)Monitor 对象的指针
- GC 标记状态:如标记-清除阶段会临时覆盖为 GC 相关标志
关键在于:JVM 通过 Mark Word 最低 2–3 位(具体取决于 JVM 版本和配置)作为 锁状态标志位(lock bits),例如:
- 01:无锁 / 偏向锁启用状态(是否真正偏向,还需看偏向位)
- 00:轻量级锁
- 10:重量级锁
- 11:GC 标志(如 CMS 的 Finalizable)
锁升级过程中 Mark Word 的变化过程
当线程执行 synchronized(obj) 时,JVM 会按顺序尝试获取锁,并相应修改 Mark Word 内容:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。
- 偏向锁获取:检查 Mark Word 是否为可偏向状态(标志位=01,且偏向锁已启用),且无其他线程竞争。若满足,用 CAS 将当前线程 ID 写入 Mark Word 的线程 ID 字段,标志位保持 01
- 偏向锁撤销:发生竞争时(如另一线程尝试加锁),触发偏向撤销。JVM 会在安全点暂停目标线程,将 Mark Word 恢复为未锁定状态(可能带原哈希码),再升级为轻量级锁
- 轻量级锁加锁:线程在自己的栈帧中创建一个 Lock Record(记录对象原始 Mark Word),然后用 CAS 尝试将 Mark Word 替换为指向该 Lock Record 的指针,标志位设为 00
- 轻量级锁膨胀:若 CAS 失败(说明存在竞争),自旋若干次后仍失败,则升级为重量级锁——将 Mark Word 设置为指向堆中 Monitor 对象的指针,标志位改为 10;原轻量级锁记录作废
Monitor 对象与重量级锁的关联
当 Mark Word 进入重量级锁状态(标志位=10),其存储的不再是线程 ID 或栈指针,而是一个指向 ObjectMonitor 结构的指针(位于 C++ 堆中)。这个 Monitor 包含:
-
_owner:持有锁的线程指针 -
_waitSet:调用wait()阻塞的线程队列 -
_entryList:等待进入临界区的线程队列(竞争失败后挂起于此) -
_recursions:重入次数(支持可重入)
此时 Mark Word 本身不再保存同步语义细节,仅作为“入口”,所有阻塞、唤醒、重入逻辑均由 Monitor 在操作系统层面协同完成(如使用 pthread_mutex 或 Windows CRITICAL_SECTION)。
验证与观察方式
可通过 JVM 参数和工具观察 Mark Word 变化:
- 启动参数:
-XX:+PrintGCDetails -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 - 使用
jol(Java Object Layout)工具打印对象内存布局:System.out.println(ClassLayout.parseInstance(obj).toPrintable());
输出中会显示 “locked”、“biased”、“neutral” 等状态,对应 Mark Word 解析结果 - 通过 JOL 查看不同锁状态下 Mark Word 十六进制值的变化(如从
0x0000000000000005→0x0000000000000200),结合 JVM 源码中markOop.hpp定义可反推状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










