AQS 的 enq 方法真难懂啊

2021-12-13 17:10:36 +08:00
 lux182
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;
                }
            }
        }
    }
只是简单的生成一个 node 作为 head ,将参数 node 变为 tail , 最后将 tail 的 prev 指向 head ,head 的 next 指向 tail 。
大牛炫技
1693 次点击
所在节点    程序员
7 条回复
lux182
2021-12-13 17:26:13 +08:00
后续时候,把参数 node 作为 tail 。tail 的 prev 指向前 tail 。前 tail 的 next 指向参数 node 。
以此形成 node 链表。 简单的几行代码就实现了,真是鬼斧神工
Canon1014
2021-12-13 17:53:43 +08:00
好像是为了解决并发性能初始化的时候首节点做了个空的虚节点,第二轮才真正的设置尾结点
说错了楼下请打醒我,面试说错就社死了
Canon1014
2021-12-13 17:54:23 +08:00
好像是为了解决并发问题,初始化的时候首节点做了个空的虚节点,第二轮才真正的设置尾结点
说错了楼下请打醒我,面试说错就社死了

性能->问题
liian2019
2021-12-13 17:54:43 +08:00
看一次忘一次
fkdog
2021-12-13 19:53:53 +08:00
其实 AQS 的本质其实就是双向链表+LockSupport.park()和 LockSupport.unpark()实现的同步器。单看 enq 并没有什么卵用,你还得结合 shouldParkAfterFailedAcquire 、unparkSuccessor 、setHeadAndPropagate 、cancelAcquire 几个方法一起看。

任意时候 node 状态都会发生变化,所以针对链表的操作用了大量的 forloop+cas 操作来保证并发安全。jdk8 版本的这个 AQS 应该是经过了 N 个版本的修订才会搞得这么零零散散一堆方法。。

我记得 8 版本以后的某个版本好像 aqs 有大篇幅的重写。。
lux182
2021-12-14 09:06:53 +08:00
@fkdog 是的 最近在看
lux182
2021-12-14 09:08:26 +08:00
@Canon1014 差不多意思

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/821919

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX