【知识点004】同步队列和等待队列
Java中同步队列与等待队列的区别
在Java并发编程中,同步队列(Sync Queue)和等待队列(Wait Queue)是两种不同的线程管理机制,它们在锁实现和线程协调中扮演着不同角色。
一、基本概念对比
特性 | 同步队列 (Sync Queue) | 等待队列 (Wait Queue) |
---|---|---|
所属机制 | AQS (AbstractQueuedSynchronizer) 核心组件 | ObjectMonitor 的等待集合 |
主要用途 | 管理等待获取锁的线程 | 管理调用wait()后等待通知的线程 |
数据结构 | CLH变体的双向链表 | 单向链表(JVM实现) |
线程状态 | 处于BLOCKED状态 | 处于WAITING/TIMED_WAITING状态 |
二、工作流程差异
同步队列工作流程
sequenceDiagram
participant ThreadA
participant SyncQueue
participant Lock
ThreadA->>Lock: 尝试获取锁
Lock->>SyncQueue: 获取失败,加入队列
SyncQueue->>ThreadA: 进入BLOCKED状态
Lock->>SyncQueue: 释放锁时唤醒下一个
SyncQueue->>ThreadA: 获取锁成功,移出队列
等待队列工作流程
sequenceDiagram
participant ThreadB
participant WaitQueue
participant Lock
ThreadB->>Lock: 获取锁后调用wait()
Lock->>WaitQueue: 加入等待队列
WaitQueue->>ThreadB: 进入WAITING状态
Note right of Lock: 释放锁
AnotherThread->>Lock: 调用notify()
Lock->>WaitQueue: 移出线程到同步队列
WaitQueue->>ThreadB: 变为BLOCKED状态
三、技术实现细节
同步队列(AQS实现)
// AbstractQueuedSynchronizer中的节点定义
static final class Node {
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter; // 用于条件队列
}
特点:
- 使用双向链表实现
- 通过CAS操作维护队列
- 实现锁的公平/非公平策略
等待队列(ObjectMonitor)
JVM层面的实现:
- 每个Java对象关联一个ObjectMonitor
- 调用wait()时进入_WaitSet链表
- notify()时从_WaitSet迁移到_EntryList
四、关键区别点
-
锁的持有关系:
- 同步队列:线程未持有锁,正等待获取
- 等待队列:线程已经持有锁后主动释放
-
状态转换:
stateDiagram-v2 [*] --> RUNNABLE RUNNABLE --> BLOCKED: 抢锁失败 BLOCKED --> RUNNABLE: 获取到锁 RUNNABLE --> WAITING: 调用wait() WAITING --> BLOCKED: 被notify后抢锁 -
唤醒机制:
- 同步队列:锁释放时自动触发
- 等待队列:需要显式调用notify()/notifyAll()
-
使用场景:
- 同步队列:ReentrantLock等显式锁实现
- 等待队列:wait/notify机制