while(某个条件) {
condition1.await();
}
lock1.unlock();
参照await的代码进行分析。首先,await()可以响应线程中断,所以一开始先判断这个时候有没有被中断(即await还没开始任何操作就遇到了中断,也许是不耐烦的用户操作引起的)。然后,把当前线程放入条件队列,释放之前已持有的锁(锁中的状态保存到线程的本地变量)。再然后,不断的查询代表当前线程的结点是否已经在锁队列上,如果不在锁队列上则阻塞。因为,把当前线程结点移到锁队列上的一定是另外一个线程(通过调用signal())。当阻塞唤醒(即从LockSupport.park()放回)之后,且查询到当前线程结点已在锁队列上时,说明此时已有其他线程成功调用了signal()或signalAll(),然后执行争夺锁的操作并把之前的锁状态还原回去,即通过acquireQueued()完成。acquireQueued()只有在成功获得锁以后才会返回,最后检查一下在前面的时间里有没有中断,如果有中断则抛出异常。Javadoc中说中断与方法的成功返回之前,中断必须优先响应,这就是因为前面的中断信息只是被记录了下来,没有及时处理,很可能是在很早之前就收到了,直到最后才有机会处理。所以,中断比上述的阻塞循环结果优先。
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);
}
其他的awaitX()系列操作,只是在阻塞循环体中增加了等待时间判断、检查有没有中断以尽早跳出循环的逻辑而已。
在await()进行等待的操作中,第一个操作是把线程放入等待队列,这是addConditionWaiter()完成的。addConditio