分析过程
// condition队列第一个节点
private transient Node firstWaiter;
// condition队列最后一个节点
private transient Node lastWaiter;
// 重新中断退出等待
private static final int REINTERRUPT = 1;
// 抛出中断异常退出等待
private static final int THROW_IE = -1;
首先来看 ConditionObject. await()
等待方法
// AbstractQueuedSynchronizer.ConditionObject
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;
}
// 使用独占不可中断模式获取锁 且 中断模式不是THROW_IE 则设置中断模式为REINTERRUPT
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters(); //【断开condition队列已取消的等待节点】
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode); // 根据中断模式进行相应处理
}
为等待队列添加新节点
// AbstractQueuedSynchronizer.ConditionObject
private Node addConditionWaiter() {
Node t = lastWaiter;
// 如果最后一个等待是取消状态则移除
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters(); // 【断开取消状态的等待结点】
t = lastWaiter;
}
// 创建状态为CONDITION的新节点
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node; // condition队列为空,添加为第一个节点
else
t.nextWaiter = node; // 将原有最后一个等待结点的前一个节点指向当前节点
lastWaiter = node; // 将当前节点设置为condition队列的最后一个节点
return node;
}
断开取消状态的等待结点
private void unlinkCancelledWaiters() {
Node t = firstWaiter; // 第一个等待节点
Node trail = null; // 存储状态为CONDITION的遗留节点
// 从头开始循环condition队列
while (t != null) {
Node next = t.nextWaiter;
// 如果等待状态为CONDITION 则将下一个节点设置为null,断开关联
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
// 如果没有遗留节点,则将下一个节点设置为第一个节点
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next; // 存在遗留节点,将下一个节点设置为遗留节点的下一个节点
// 遍历至尾部,将condition队列最后一个节点指向遗留节点
if (next == null)
lastWaiter = trail;
}
else
trail = t; // 记录状态为CONDITION的遗留节点
t = next; // 循环下一个节点
}
}
为当前状态值调用释放方法,返回保存状态,在失败时取消节点并抛出异常
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;
}
}
判断等待队列上的节点是否正在同步队列上等待获取锁
final boolean isOnSyncQueue(Node node) {
// 如果节点等待状态为CONDITION 或 节点的前驱节点为空,则返回false
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); // 从队列尾部开始查找当前节点是否处于同步队列中
}
ConditionObject.signal()
唤醒方法
// AbstractQueuedSynchronizer.ConditionObject
public final void signal() {
// 判断是否处于独占状态
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first); // 【执行唤醒操作】
}
执行唤醒操作
private void doSignal(Node first) {
do {
// 将头节点设置为头节点的下一个节点并判断是否为空
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null; // 如果为空则将最后一个节点设置为空
first.nextWaiter = null; // 将头节点的下一节点设置为空
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
转换条件队列节点至同步队列
final boolean transferForSignal(Node node) {
// CAS设置等待状态,设置失败说明节点已经被取消
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
Node p = enq(node); // 将节点添加至同步队列
int ws = p.waitStatus;
// 如果节点被取消 或 CAS设置等待状态为SIGNAL失败
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread); // 唤醒节点所属线程
return true;
}
主要的等待唤醒方法分析完成。
参考资料
并发编程的艺术