java中synchronized锁机制通过修改对象头mark word字段实现,而非直接写入锁标记;mark word复用存储锁状态(无锁001、偏向锁101、轻量级锁00、重量级锁10),并随竞争自动升级,最终由monitor承载重量级锁语义。

Java 中 synchronized 关键字的锁机制并不直接“在对象头中写入锁标记”,而是通过修改对象头(Object Header)中的特定字段(主要是 Mark Word)来实现锁状态的记录和管理。这个过程由 JVM 在运行时动态完成,底层依赖于操作系统互斥量(mutex)、CAS 操作和对象头结构。
对象头中的 Mark Word 存储锁状态
每个 Java 对象在堆内存中都有一个对象头(Header),其中 Mark Word(通常 64 位或 32 位,取决于 JVM 配置)是关键部分,用于存储哈希码、GC 分代年龄、锁标志位等信息。JVM 利用 Mark Word 的若干低位(如低 2–3 位)编码当前锁的状态:
- 无锁状态(001):对象未被锁定,Mark Word 存储哈希码或分代年龄等;
- 偏向锁(101):Mark Word 记录持有锁的线程 ID 和 epoch(用于批量撤销);
- 轻量级锁(00):Mark Word 被替换为指向线程栈中 Lock Record 的指针;
- 重量级锁(10):Mark Word 指向操作系统互斥量(monitor)的指针;
- GC 标志(11):如 CMS 使用的 marked for GC 状态,与锁无关。
锁升级过程由 JVM 自动触发
锁不是一开始就“标记”好的,而是根据竞争情况逐步升级(偏向锁 → 轻量级锁 → 重量级锁)。例如:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 首次进入同步块且无竞争时,JVM 尝试将 Mark Word 设置为偏向锁状态(通过 CAS 修改);
- 发生竞争(另一个线程尝试获取同一把锁)时,偏向锁被撤销,升级为轻量级锁:当前线程在栈中创建 Lock Record,并用 CAS 将其地址写入 Mark Word;
- 若自旋失败(多次 CAS 获取锁失败),JVM 将锁膨胀为重量级锁:分配 monitor 对象,将 Mark Word 更新为指向该 monitor 的指针,并挂起等待线程。
Monitor 是重量级锁的实际载体
当锁升级到重量级,synchronized 的语义就委托给 Monitor 实现。Monitor 是 JVM 内部对象(C++ 实现),包含:
- _owner:记录持有锁的线程;
- _EntryList:等待获取锁的阻塞线程队列;
-
_WaitSet:调用
wait()后挂起的线程队列。
此时对象头的 Mark Word 不再保存线程 ID 或栈帧指针,而是存 monitor 的地址 —— 这才是“锁标记”真正落地的位置。
注意:没有独立的“锁标记字段”
对象头中并不存在一个叫 lock_flag 的专用字段。所谓“锁标记”,实质是 Mark Word 多重语义复用的结果:同一段二进制数据,在不同状态下承载不同含义(哈希码 / 线程ID / 指针)。JVM 通过位运算和 CAS 原子操作识别并切换这些状态,整个过程对 Java 开发者透明。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










