AbstractQueuedSynchronizer中CAS的疑惑

发布于 2022-09-04 18:17:04 字数 528 浏览 18 评论 0

这段代码是AQS框架中将当前节点入队的操作。

Node pred = tail;
if (pred != null) {
    node.prev = pred;
    if (compareAndSetTail(pred, node)) {
        pred.next = node;
        return node;
    }
}

上面代码中pred被赋值为尾节点,node为当前节点。我理解的将新节点插入链表尾处的逻辑应当如下:
node.prev = pred; node节点的前驱指向尾节点
pred.next = node; 将尾节点的后继设置为当前节点
tail = node; 将node节点设置为尾节点
对于上面代码我的疑问如下:
如果尾节点不为空,node节点的前驱会指向尾节点,然后调用CAS交换pred和node的值。
此时pred(即tail)的值应该已经是当前节点node的值了,再执行pred.next=node是什么意思呢,这是否存在逻辑问题?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ヅ她的身影、若隐若现 2022-09-11 18:17:04

TZ可能对compareAndSetTail的理解有误。

private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

在AbstractQueuedSynchronizer的tailOffset位置比较pred的值和期望的node值,如果相同则更新tailOffset位置的值。

static {
    tailOffset = unsafe.objectFieldOffset
    (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
    ...
}

compareAndSetTail(pred, node) 这句代码执行完成之后,被修改只是对象AbstractQueuedSynchronizer的tailOffset的值,也就是成员变量tail的值,对于pred的值没有任何影响。至于双向链表,尾部插入,逻辑上没有问题。

扮仙女 2022-09-11 18:17:04

这个设计是一个双向链表.
B.prev == A
A.next == B

compareAndSetTail 设置成功只是将 tail 更新为当前node. pred.next 是将上一个尾部节点的next设置为当前node这逻辑不存在问题.

我不咬妳我踢妳 2022-09-11 18:17:04

compareAndSetTail(pred,node);的意思是说:比较pred的值和tail的值,如果相等,则将node的值赋给tail,那么此时tail就指向了node,node节点变成了新的tail,而pred没有变,还是之前tail指向的节点;

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文