java重量级锁膨胀为monitor后,底层通过futex(linux)、waitforsingleobject(windows)等系统原语实现线程阻塞与唤醒,而非直接使用pthread_mutex_t;objectmonitor中的_mutex仅用于保护自身元数据,并非同步业务线程的锁。

Java 重量级锁(Heavyweight Lock)在膨胀为 Monitor 后,底层确实会借助操作系统的互斥量(Mutex)机制来实现线程阻塞与唤醒,但不是直接使用 pthread_mutex_t 这类用户态 Mutex,而是通过 JVM 内部封装的 操作系统原语(如 futex、WaitForSingleObject、pthread_cond_wait + pthread_mutex_t 组合) 来协作完成。
Monitor 膨胀触发条件
当一个对象锁经历多次自旋失败(比如 -XX:PreBlockSpin,默认10次),或存在多个线程竞争、且等待时间较长时,JVM 会将偏向锁/轻量级锁升级为重量级锁。此时对象头 Mark Word 被替换为指向 ObjectMonitor 结构的指针,该结构由 JVM 在 C++ 层分配(位于 HotSpot 的 ObjectMonitor.hpp 中)。
ObjectMonitor 如何关联操作系统锁
ObjectMonitor 内部包含两个关键操作系统级同步组件:
- _mutex:一个平台相关的互斥量(如 Linux 下是 pthread_mutex_t),用于保护 Monitor 自身字段(如 _owner、_EntryList、_WaitSet)的并发修改;
- _cond:一个条件变量(如 Linux 下是 pthread_cond_t),用于挂起和唤醒等待线程。
注意:这两个结构不直接参与 Java 层 synchronized 的“加锁逻辑”,而是服务于 Monitor 管理——比如确保只有一个线程能修改 _owner 字段,或安全地将线程放入 _EntryList 并休眠。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
线程阻塞与唤醒的真实路径
真正让线程进入 OS 级阻塞状态的,并非 _mutex,而是基于以下机制:
-
Linux(主流 JDK):优先使用 futex(fast userspace mutex)。ObjectMonitor::enter() 在发现锁被占用后,先尝试 CAS 获取,失败则调用
os::Linux::safe_suspend()或更底层的futex(FUTEX_WAIT),使线程陷入内核等待队列;唤醒时调用futex(FUTEX_WAKE)。 -
Windows:使用
WaitForSingleObject配合CreateSemaphore或CRITICAL_SECTION+SignalObjectAndWait实现类似语义。 -
macOS:基于
pthread_mutex和pthread_cond,但同样封装在 os_posix.cpp 中,对 Java 层透明。
也就是说:futex 才是实际承担“阻塞/唤醒”的核心系统调用,而 ObjectMonitor::_mutex 只是保护 Monitor 元数据的内部锁,不暴露给业务线程。
为什么不用纯 pthread_mutex_t 实现 synchronized?
因为 pthread_mutex_t 本身不具备 Java 锁所需的语义:
- 无法支持
wait()/notify()—— 它没有条件队列概念; - 不区分“竞争锁失败”和“主动等待条件”两种阻塞场景;
- 缺乏与 GC、线程中断、锁重入计数等 JVM 特性的集成能力。
JVM 必须自己维护 owner、entry list、wait set、reentrant count 等状态,再通过操作系统原语实现底层调度,才能满足 synchronized 的完整行为规范。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










