AQS clh
时间: 2025-06-18 07:53:26 浏览: 3
### AQS与CLH队列的实现细节
AQS(AbstractQueuedSynchronizer)是Java并发包中的一个核心组件,用于构建锁和其他同步器的基础框架。它内部使用了一个FIFO的CLH队列来管理线程的等待和唤醒过程[^1]。
#### 1. CLH队列的基本概念
CLH(Craig, Landin, and Hagersten)队列是一种基于链表的队列结构,最初设计用于自旋锁。在AQS中,CLH队列被改造为阻塞队列,用于管理线程的排队和唤醒。每个节点代表一个等待获取资源的线程。当线程尝试获取锁失败时,会创建一个新的节点并将其加入队列末尾[^4]。
```java
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
```
上述代码展示了如何将一个线程包装成`Node`对象,并将其插入到CLH队列中。如果当前队列尾部不为空,则尝试通过CAS操作快速将新节点添加到队列末尾;否则调用`enq()`方法进行完整初始化。
#### 2. AQS的核心方法
AQS的核心逻辑围绕以下几个方法展开:
- **`tryAcquire()`**:由子类实现,用于尝试获取锁。如果返回`false`,则调用`addWaiter()`将线程加入队列。
- **`acquireQueued()`**:将线程放入等待状态,直到成功获取锁或被中断。
- **`isHeldExclusively()`**:判断当前线程是否独占持有锁,主要用于条件变量的支持[^3]。
#### 3. 条件变量的支持
AQS还支持条件变量(Condition),通过`ConditionObject`类实现。线程可以通过`await()`方法进入等待状态,并通过`signal()`方法唤醒其他线程。这一机制类似于`Object`类中的`wait()`和`notify()`方法[^2]。
```java
public class ConditionAwaitSignalDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " come in.");
lock.lock();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName() + " 换醒.");
}, "Thread A").start();
new Thread(() -> {
try {
lock.lock();
condition.signal();
System.out.println(Thread.currentThread().getName() + " 通知.");
} finally {
lock.unlock();
}
}, "Thread B").start();
}
}
```
上述代码演示了`Condition`接口的使用方式。`Thread A`调用`await()`进入等待状态,而`Thread B`通过`signal()`唤醒等待中的线程[^2]。
#### 4. 队列的延迟初始化
CLH队列在AQS中的实现具有延迟初始化的特点。只有当第一个线程尝试获取锁失败时,才会创建队列的第一个节点(即头节点)。头节点是一个特殊的哑节点,其`thread`字段为`null`。
### 总结
AQS通过CLH队列实现了线程的有序等待和唤醒机制。它的设计灵活且高效,能够满足多种同步场景的需求。无论是独占锁还是共享锁,AQS都能通过统一的队列管理机制提供支持。
阅读全文
相关推荐


















