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);
}
首先将节点加入单向的等待链表中
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
// 加入等待单向链表中
Node node = new Node(Thread.currentThread(), Node.CONDITION);
// 若是空就将头尾节点都指向当前节点
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
释放当前线程的所有锁,并记录重入的次数
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
释放锁
public final boolean release(int arg) {
// 将state赋值为0,当前持锁线程为null,就是Lock.unlock
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
阻塞当前线程
final boolean isOnSyncQueue(Node node) {
// 满足条件进行阻塞
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
return findNodeFromTail(node);
}
判断是不是头结点之后的,若是重新竞争的锁,若不是继续阻塞
ps:signal方法会将该节点从条件队列中,转移到同步队列中
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 若前置是头节点,并且获得锁成功
if (p == head && tryAcquire(arg)) {
// 成为新的头结点
setHead(node);
// 将原头节点从队列中删除
p.next = null; // help GC
failed = false;
return interrupted;
}
// 若不是头节点继续阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}