先上代码:
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)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
首先调用addConditionWaiter把当前节点加入到condition队列。然后调用fullyRelease释放当前节点获得的锁。然后判断是否在sync队列(其实就是判断是否有notify),如果没有notify,那么只有阻塞当前线程,如果有notify信号,那么按照acquire锁的逻辑再走一遍。当await返回的时候,当前线程又持有锁了。
里面的核心判断是isOnSyncqueue(),来看下什么时候返回为真:
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
可以看到transferForSignal里面有把node从condition队列移到sync队列的逻辑,并且unpark了node持有的线程,从阻塞状态中醒过来,这样就可以继续竞争锁了。其中signal使用了这个方法,以使阻塞的线程从await中醒过来。