当我阅读acquireQueued
方法的代码时,我正在研究AbstractQueuedSynchronizer类的源代码:
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);
}
}
语句final Node p = node.predecessor();
表示获取当前节点的上一个节点p
。下一条if语句尝试比较p
节点和head
节点。
我的疑问是head
节点如何更改,以便代码可以输入if语句,以及发生了更改的代码块
[似乎在shouldParkAfterFailedAcquire
/parkAndCheckInterrupt
/release
/ unparkSuccessor
方法中找不到代码块
显然,当第二个节点被唤醒并tryAcquire成功时,它成为头节点。setHead(node);
然后,当第三个节点被唤醒时,头节点发生更改。
输入if语句不一定表示头部已更改。如果该节点的前一个节点被取消,则该节点可以充当头节点的后节点。参见shouldParkAfterFailedAcquire
方法中的详细信息