gpt4 book ai didi

java - 如何理解AQS上的 "unparkSuccessor"函数

转载 作者:行者123 更新时间:2023-12-01 09:06:43 25 4
gpt4 key购买 nike

当我阅读Java关于AQS(AbstractQueuedSynchronizer)的源码时,我有一个疑问。

private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);

/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}

主要疑问是:

if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}

为什么如果取消或明显为空,则从尾部向后遍历以找到实际的未取消后继者?而不是从头部去寻找实际的非取消继任者?谢谢您的回答。

最佳答案

这是一个保守的设计。 next 是在 enq 方法中赋值的,设置新的 tail 并将前一个 tail 的 next 引用链接到新的 tail 不是原子操作。在 for 循环中,它首先分配 prev 字段,如果赢得了 compareAndSetTail,则将 prev 的 next 分配给新的尾节点。因此,如果 next 不为 null 并且 next 未取消,则 next 路径是一种优化,而不是向后遍历。

So seeing a null next field does not necessarily mean that node is at end of queue. The next field of cancelled nodes is set to point to the node itself instead of null, to make life easier for isOnSyncQueue.

private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}

关于java - 如何理解AQS上的 "unparkSuccessor"函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41208482/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com