Java重量级锁底层依赖操作系统互斥量和条件变量实现阻塞唤醒:Monitor绑定pthread_mutex_t和pthread_cond_t,通过futex/pthread_cond_wait原子地释放锁并挂起线程,notify或锁释放时唤醒EntryList中线程。

Java 重量级锁(即 synchronized 在竞争激烈时升级后的 Monitor 锁)在底层依赖操作系统提供的互斥量(mutex)和条件变量(condition variable)来实现线程的阻塞与唤醒,而非单纯靠 JVM 自旋或用户态调度。
Monitor 与操作系统的映射关系
JVM 中每个 Java 对象关联一个 Monitor 对象(C++ 实现,位于 HotSpot 的 ObjectMonitor 类),当锁升级为重量级后,Monitor 内部会绑定一个操作系统级别的互斥量(如 Linux 的 pthread_mutex_t)和一个条件变量(如 pthread_cond_t)。
- 互斥量用于保护 Monitor 内部状态(如 _owner、_EntryList、_WaitSet 等字段),确保同一时刻只有一个线程能修改这些元数据
- 条件变量不直接保护共享数据,而是配合互斥量,提供“等待某条件成立”和“通知条件可能已变”的机制
线程阻塞:进入 EntryList 或 WaitSet 时调用系统 futex/pthread_cond_wait
当线程尝试获取已被占用的重量级锁失败时:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先通过 CAS 尝试将自己加入 Monitor 的 _EntryList(竞争队列),该过程需持有 Monitor 关联的互斥量
- 随后调用 pthread_cond_wait(&_cond, &_mutex) —— 这个系统调用会原子地:
① 释放关联的互斥量(_mutex)
② 将当前线程挂起(转入内核等待队列)
③ 等待其他线程对其发出 signal/broadcast - 在 Linux 上,HotSpot 实际常使用更轻量的 futex(fast userspace mutex)系统调用替代 pthread_cond_wait,但语义一致:用户态判断无锁则陷入内核休眠
线程唤醒:notify/notifyAll 或锁释放时触发系统唤醒原语
唤醒发生在两类场景:
立即学习“Java免费学习笔记(深入)”;
- 显式唤醒:调用 Object.notify() 时,JVM 从 _WaitSet 挑选一个线程,将其移入 _EntryList,再调用 pthread_cond_signal() 唤醒它
- 隐式唤醒:持有锁的线程执行 monitorexit(如 synchronized 块结束),JVM 释放 Monitor 关联的互斥量,并检查 _EntryList 是否非空;若有等待线程,则调用 pthread_cond_signal() 或 broadcast() 唤醒至少一个
- 被唤醒的线程从内核返回用户态后,会重新竞争获取那个互斥量(_mutex),成功后才能继续执行锁逻辑(比如检查是否轮到自己获得 Monitor 所有权)
关键细节:为什么需要互斥量 + 条件变量配合?
单独用互斥量无法实现“等待某个状态成立”,因为:
- 若只 lock/unlock,线程只能轮询检查(忙等),浪费 CPU
- 若在 unlock 后 sleep,存在竞态:unlock 和 sleep 之间,另一线程可能已完成 notify,导致唤醒丢失
- pthread_cond_wait 的原子性(释放锁 + 进入等待)彻底避免了该竞态 —— 它是操作系统保障的同步原语

















