开篇语
条件队列是 AQS 中最容易被忽视的一个细节。大部分时候,我们都用不上条件队列,但是这并不说明条件队列就没有用处了,它反而是我们学习生产者-消费者模式的最佳教材。
什么是条件队列
条件队列是指一个阻塞队列,其中的元素是等待某个条件成立的线程。在 Java 的同步机制中,条件队列通常用于实现线程等待和唤醒的操作。当条件不满足时,线程会被加入到条件队列中等待;当条件满足时,线程会被从条件队列中移除并继续执行。
AQS 中的条件队列
AbstractQueuedSynchronizer 中的条件队列是一个单向链表,每个节点代表一个等待线程。条件队列的头节点是一个特殊的节点,表示等待队列的头部。当条件不满足时,线程会被加入到条件队列的尾部等待;当条件满足时,线程会从条件队列中移除并加入到同步队列中等待获取锁。
AbstractQueuedSynchronizer 中的条件队列是通过内部维护的等待队列和同步队列实现的。当线程调用 await() 方法时,它会被加入到等待队列中等待条件满足。
当有其他线程调用了条件队列的 signal() 方法,线程则会从条件队列中移除,并加入到同步队列中等待获取锁。
方法解析
await
该方法的作用是将当前线程加入条件队列并阻塞,直到被唤醒或中断。
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
复制代码
- 如果线程被中断过,那么直接抛出中断异常
- 创建一个 Condition 类型的节点,并插入到等待队列中。
private Node addConditionWaiter(