重量级锁在轻量级锁自旋失败后触发,jvm将对象头mark word替换为指向monitor的指针,monitor内封装操作系统互斥量(如futex),线程通过系统调用阻塞/唤醒,依赖内核调度保证可靠性但开销大。

重量级锁触发操作系统底层互斥量,本质是 JVM 主动把线程同步任务“交出去”——从用户态交给操作系统内核来管。这个过程不是一上来就发生的,而是在锁竞争加剧、自旋已无意义时,由 JVM 判定并升级完成的。
触发前提:轻量级锁自旋失败
当多个线程竞争同一把锁,JVM 首先尝试用轻量级锁(基于 CAS 和栈上锁记录)。但线程不会无限自旋,一旦达到阈值(默认 10 次),或 JVM 检测到竞争变长、线程数增多,就会放弃自旋策略。此时,继续忙等既浪费 CPU,又无法提升获取成功率,升级为重量级锁就成了合理选择。
对象头切换:指向 Monitor 对象
升级发生时,JVM 修改对象头 Mark Word 的锁标识位为 10(表示重量级锁),并将原本存储锁记录指针的位置,替换为一个指向堆中 Monitor 对象 的指针。这个 Monitor 不是 Java 层面的类,而是 JVM 内部结构,它内部封装了一个操作系统级的互斥量(如 Linux 下的 futex 或 POSIX 的 pthread_mutex_t)。
系统调用:线程阻塞与唤醒全由 OS 接管
此后,线程获取锁失败不再自旋,而是执行如下动作:
- 调用底层系统 API(例如
pthread_mutex_lock),进入内核态 - 操作系统将该线程状态设为 BLOCKED 或 WAITING,移出运行队列,让出 CPU
- 线程挂起,等待被唤醒;其调度、等待队列管理、唤醒时机全部由 OS 负责
- 当持有锁的线程释放锁时,JVM 调用对应系统 API(如
pthread_mutex_unlock),通知操作系统唤醒等待队列中的一个或多个线程
为什么必须依赖操作系统互斥量
因为用户态程序无法直接控制线程调度和 CPU 时间片分配。只有内核具备暂停/恢复线程、管理等待队列、保证唤醒公平性等能力。重量级锁正是通过这种“委托”机制,换来强可靠性——即使在高并发、长时间持锁场景下,也能避免忙等、死循环或资源争抢失控。代价则是每次加锁/解锁都伴随一次用户态到内核态的切换,开销明显高于偏向锁和轻量级锁。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











