Java重量级锁的等待队列由JVM在Monitor层面维护,线程阻塞与唤醒依赖操作系统内核原语(如Linux的pthread_cond_wait),分_EntryList(竞争锁)和_WaitSet(wait()等待通知)两个队列,无公开API可操作,唤醒后仍需重新竞争锁。

Java 中重量级锁的等待队列由 JVM 在对象监视器(Monitor)层面维护,线程管理不依赖 Java 层代码,而是由操作系统内核和 JVM 协同完成。
等待队列由 Monitor 内部结构管理
当线程竞争 synchronized 锁失败且锁已升级为重量级时,JVM 会将该线程封装为 ObjectWaiter 对象,加入 Monitor 的 _WaitSet 或 _EntryList(具体取决于线程是因 wait() 还是竞争进入而阻塞):
- _EntryList 存储正在等待获取锁的线程(即“争用队列”),按先进先出或根据操作系统调度策略排序;
- _WaitSet 存储调用 object.wait() 主动释放锁并等待通知的线程;
- JVM 不保证严格 FIFO,实际顺序受操作系统线程调度影响,但会尽力维持公平性倾向。
线程阻塞与唤醒由 JVM 委托给操作系统
进入等待队列后,线程不会轮询,而是通过 JVM 调用操作系统原语挂起:
- 在 Linux 上,通常使用 pthread_mutex_lock / pthread_cond_wait 等 POSIX 线程原语;
- 线程状态变为 BLOCKED(JVM 层面)或 TASK_INTERRUPTIBLE(内核层面);
- 当持有锁的线程退出同步块、调用 notify()/notifyAll(),或发生中断时,JVM 从对应队列中选取线程唤醒,并触发系统调用使其重新参与 CPU 竞争。
唤醒策略与竞争处理
被唤醒的线程并不立即获得锁,而是重新进入 _EntryList 竞争:
立即学习“Java免费学习笔记(深入)”;
- notify() 随机唤醒一个 _WaitSet 中的线程,该线程被移到 _EntryList 尾部;
- notifyAll() 将所有 _WaitSet 线程移入 _EntryList,后续仍需重新抢锁;
- 若此时锁空闲,JVM 可能直接授予锁避免再次挂起,但无绝对保证——仍可能因调度延迟被其他线程抢占。
开发者不可直接操作等待队列
Java 提供的 API(如 Thread.getState())只能观察线程状态(BLOCKED / WAITING / TIMED_WAITING),无法查询或干预队列内部结构:
- 没有公开接口获取等待队列长度或遍历等待线程;
- Thread.interrupt() 可打断 WAITING/TIMED_WAITING 状态线程,使其抛出 InterruptedException 并退出 wait(),但对 BLOCKED 状态无效;
- 过度依赖等待队列行为(如假设唤醒顺序)会导致不可靠逻辑,应通过合理设计同步协议规避。
不复杂但容易忽略:重量级锁的队列管理本质是 JVM 对操作系统线程机制的封装,理解其背后依赖的是内核调度而非 Java 代码,才能写出健壮的并发逻辑。


















