直接看到aqs的ConditionObject类的await方法。
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//将当前线程包装为node,添加到条件队列中(现在节点是在条件等待队列中)
Node node = addConditionWaiter();
//释放锁资源(其他线程可以去抢锁了)
int savedState = fullyRelease(node);
int interruptMode = 0;
//isOnSyncQueue判断该节点是否在同步等待队列(不是条件等待队列)中
while (!isOnSyncQueue(node)) {
//休眠当前线程
LockSupport.park(this);
//是否被打断过,被打断过返回-1或者1,直接跳出循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//当该node被signal进入同步等待队列中,之后被唤醒
//或者该线程被打断醒来
//执行下面代码
//acquireQueued之前已经讲过了,这里会去获取锁,获取不到则休眠
//如果获取到锁且返回true,说明在同步队列中获取锁时被打断过
//且 如果 interruptMode 不为THROW_IE(不是在 条件等待队列中 被打断唤醒 进去同步队列的)
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
//interruptMode 设置为REINTERRUPT (1)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
//清除被取消的节点
unlinkCancelledWaiters();
//被打断过
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
//抛出中断异常
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
//重新中断一次,设置中断标识,来标识曾经被中断过。
selfInterrupt();
}
private Node addConditionWaiter() {
//获取到lastWaiter(队尾的等待节点),初始时为空
Node t = lastWaiter;
//如果lastWaiter不为空,且lastWaiter的waitStatus不为CONDITION ,说明lastWaiter被取消了
if (t != null && t.waitStatus != Node.CONDITION) {
//将所有被取消的节点从等待队列中去除
unlinkCancelledWaiters();
//去除后,重新获取lastWaiter
t = lastWaiter;
}
//将当前线程封装为node节点,waitStatus为CONDITION
Node node = new Node(Thread.currentThread(), Node.CONDITION);
//如果lastWaiter为空,队列中啥都没有
if (t == null)
//设置firstWaiter(队头的等待节点)为node
firstWaiter = node;
//如果不为空,将lastWaiter的nextWaiter指向当前节点
else
t.nextWaiter = node;
//node成为lastWaiter
lastWaiter = node;
return node;
}
private void unlinkCancelledWaiters() {
//获取firstWaiter
Node t = firstWaiter;
Node trail = null;
//当t为空,退出循环
while (t != null) {
//获取下一个节点
Node next = t.nextWaiter;
//如果当前节点被取消
if (t.waitStatus != Node.CONDITION) {
//将当前节点的下一个节点置为空
t.nextWaiter = null;
//trail为空(还没找到未被取消的正常节点)
if (trail == null)
//头结点被取消了,头结点置为下一个节点
firstWaiter = next;
//trail已经记录了正常等待的节点
else
//使该正常等待的节点的下一个节点指向next
trail.nextWaiter = next;
//next为空(队列遍历完了)
if (next == null)
//将lastWaiter置为trail
lastWaiter = trail;
}
//当前节点没被取消了
else
//trail记录着每次循环找到的正常等待节点
trail = t;
//将t设置为下一个节点
t = next;
}
}
final int fullyRelease(Node node) {
boolean failed = true;
try {
//获取当前的state
int savedState = getState();
//release之前的文章已经讲过
//释放锁,唤醒正常排队的线程(如果有的话)
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
//将node的waitStatus设置为CANCELLED
node.waitStatus = Node.CANCELLED;
}
}
final boolean isOnSyncQueue(Node node) {
//如果当前节点的waitStatus为CONDITION,返回false
//或者节点的前置节点为空(条件队列的节点的prev 和 next 属性为空)
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
//该节点的后置节点不为空
if (node.next != null) // If has successor, it must be on queue
return true;
return findNodeFromTail(node);
}
private boolean findNodeFromTail(Node node) {
//获取同步等待队列的尾节点
Node t = tail;
//死循环
for (;;) {
//同步等待队列中有该节点
if (t == node)
return true;
//遍历完都没找到,则不在同步等待队列中
if (t == null)
return false;
t = t.prev;
}
}
private int checkInterruptWhileWaiting(Node node) {
//判断是否被打断过,并清除打断标志,被打断过则执行transferAfterCancelledWait
return Thread.interrupted() ?
//transferAfterCancelledWait返回值:
//返回true,则说明节点是被打断唤醒放入同步等待队列而不是被signal放入同步等待队列,则返回THROW_IE (-1)
//返回false,说明节点已经被signal到同步等待队列,则返回REINTERRUPT (1)
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
//没有打断返回0
0;
}
final boolean transferAfterCancelledWait(Node node) {
//cas设置该节点的状态为0
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
//cas设置成功,将node设置到同步等待队列的队尾
//enq之前的文章已经说过了
enq(node);
//返回true
return true;
}
//cas失败,则说明该节点已经被signal了,要去进入同步等待队列了
//直到节点进入同步等待队列完毕前,该方法都不返回
while (!isOnSyncQueue(node))
Thread.yield();
//返回false
return false;
}
直接看到aqs的ConditionObject类的signal方法和signalall方法。
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//获取firstWaiter
Node first = firstWaiter;
if (first != null)
//唤醒节点
doSignal(first);
}
private void doSignal(Node first) {
do {
//first要被唤醒进入同步等待队列中,将firstWaiter设置为下一个节点
if ( (firstWaiter = first.nextWaiter) == null)
//没有下一个节点了,将lastWaiter 置为空
lastWaiter = null;
//将first的nextWaiter置为空
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
//这里循环调用transferForSignal方法,如果first没有被取消,则调用完transferForSignal后,整个方法结束
//如果first被取消,则执行(first = firstWaiter) != null),
//被唤醒的节点被取消了则唤醒下一个节点,接着循环 , 如果没有下一个节点,则跳出循环。
}
final boolean transferForSignal(Node node) {
//cas将node的WaitStatus设置为0
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
//如果设置失败,说明waitstatus不为CONDITION ,节点只可能是被取消了。
//返回false
return false;
//将该节点设置到同步等待队列的队尾,
//这里返回的p是该节点进入队尾后的前一个节点
Node p = enq(node);
int ws = p.waitStatus;
//如果p的waitStatus大于0,则说明p被取消了,没法再唤醒node了,所以这里直接唤醒node,让node去竞争锁
//如果p的waitStatus不大于0,cas将p的waitstatus改为SIGNAL,以后要去唤醒node
//cas设置p的waitstatus为SIGNAL失败,则直接唤醒node,让node去竞争锁
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
//node没有被取消,返回true
return true;
}
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//获取firstWaiter
Node first = firstWaiter;
if (first != null)
//唤醒条件等待队列的所有节点
doSignalAll(first);
}
private void doSignalAll(Node first) {
//要唤醒调节键队列的所有节点,所以将firstWaiter 和 lastWaiter 都置为空
lastWaiter = firstWaiter = null;
do {
//获取头结点的下一个节点
Node next = first.nextWaiter;
//将要唤醒的节点的nextWaiter 置空
first.nextWaiter = null;
//唤醒该节点,进入同步等待队列
transferForSignal(first);
//first 设置为next
first = next;
} while (first != null);
//循环直到first的下一个节点为空
}
到此。条件队列的等待和唤醒方法也就解析完了。