当我读到Java(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;
}如果已取消或明显为空,为什么要从tail向后遍历以找到实际未取消的后继者?而不是从头中找出实际的未注销继任者?谢谢你的回答。
发布于 2017-05-17 16:37:52
这是一个保守的设计。next是在enq方法中分配的,设置新的尾部并将前一个尾部的next引用链接到新的尾部不是原子操作。在for循环中,它首先分配prev字段,如果赢得compareAndSetTail,则将prev分配到新尾节点的下一个。因此,如果next不为null且next不被取消,则next路径是优化的,而不是向后遍历。
,所以看到空的next字段并不一定意味着节点在队列的末尾。已取消节点的下一个字段被设置为指向节点本身,而不是null,以使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;
}
}
}
}https://stackoverflow.com/questions/41208482
复制相似问题