public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
如上,注释说了因为第一次入队,可能出现 head 初始化了,head.next 没有初始化。那就是定位到如下地方:
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))//先设置 head
tail = head;//再设置 tail
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
看了网上的解释,都说这样就可以让 hasQueuedPredecessors 中两个域读取完只有几种情况发生:
如下图,把 hasQueuedPredecessors 的两个读取域标记为蓝色,enq 的两次设置不标记颜色。无论怎么移动(保持先后相对位置),都只会出现上面几种情况。这好像证明了我的上面的观点。
但是此时,我又想起来多线程不是有个 happen-before 还是什么玩意,意思就是说,多线程下,每个线程只会考虑单线程下的正确执行。 而且 hasQueuedPredecessors 里 读取 tail 和读取 head 没有什么依赖关系,那上图的 标记蓝色的 读取 tail 和读取 head 岂不是可以随便交换顺序,也就不能维持 ,读取 tail 先与 读取 head 的相对顺序了吗?那岂不是 就会出现 tail 为 null,head 不为 null 的相反情况了?
哎,想太多,要疯了。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.