关于 ConcurrentLinkedQueue 的一些疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
GiftedJarvis
V2EX    Java

关于 ConcurrentLinkedQueue 的一些疑问

  •  1
     
  •   GiftedJarvis Oct 12, 2021 2273 views
    This topic created in 1658 days ago, the information mentioned may be changed or developed.

    关于 ConcurrentLinkedQueue 的一些疑问

    private transient volatile Node<E> head; private transient volatile Node<E> tail; public ConcurrentLinkedQueue() { head = tail = new Node<E>(null); } public boolean offer(E e) { checkNotNull(e); final Node<E> newNode = new Node<E>(e); for (Node<E> t = tail, p = t;;) { Node<E> q = p.next; if (q == null) { if (p.casNext(null, newNode)) { if (p != t) casTail(t, newNode); return true; } } else if (p == q) p = (t != (t = tail)) ? t : head; else p = (p != t && t != (t = tail)) ? t : q; } } boolean casNext(Node<E> cmp, Node<E> val) { return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } 

    前提

    使用 ConcurrentLinkedQueue() 构造一个对象,并首次调用 offer() 方法

    问题

    当代码执行到 if (q == null) 时,head == tail,但是当执行完 p.casNext(null, newNode),为什么是 head 成为了 { item = 1, next = null },也就是 newNode,而 tail 变成了 { item = null, next = tail ( tail 本身) } ? p 是从 t 赋值来的,而 t 是从 tail 赋值来的,tail == head,为什么调用 p.casNext(null, newNode) 会同时改变 head 和 tail 的值,且 head 和 tail 的值不一样了?

    5 replies    2021-10-14 17:35:18 +08:00
    XYxe
        1
    XYxe  
       Oct 12, 2021   1
    GiftedJarvis
        2
    GiftedJarvis  
    OP
       Oct 12, 2021
    @XYxe 十分感谢,困扰两天了,根本没往 IDEA 的问题上面想
    Chinsung
        3
    Chinsung  
       Oct 12, 2021   1
    @GiftedJarvis 之前遇到过一个类似问题,某个很 SB 的框架类在 toString 里面修改了对象的值,debug 阶段 idea 会调用 toString 以输出对象的 view,然后 debug 半天一直发现值和预想的不一样。
    huang119412
        4
    huang119412  
       Oct 13, 2021
    老问题了 https://juejin.cn/post/6844904177437523982 不仅 idea 有问题
    GiftedJarvis
        5
    GiftedJarvis  
    OP
       Oct 14, 2021
    各位大佬, 关闭 IDEA Debugger toString 后确实解决问题了, 这是新的结果:

    初始化
    head { item = null, next = null }
    tail { item = null, next = null }

    第一次添加值完成后
    head { item = null, next = { item = 1, next = null } }
    tail { item = null, next = { item = 1, next = null } }

    第二次添加值完成后
    head { item = null, next = { item = 1, next = { item = 2, next = null } } }
    tail { item = 2, next = null }

    第三次添加值完成后
    head { item = null, next = { item = 1, next = { item = 2, next = { item = 3, next = null } } } }
    tail { item = 2, next = { item = 3, next = null } }

    第四次添加值完成后
    head { item = null, next = { item = 2, next = { item = 3, next = { item = 4, next = null } } } }
    tail { item = 4, next = null }

    然后, 有了新的疑问, 为什么要这样设计呢?
    tail 并不一定是尾结点, 为此还需要重新确定尾结点, 难道是因为性能吗? 这样可以少进行一次 casTail(t, newNode), 但代码可读性真的降低了好多呀
    About     Help     Advertise     Blog     API     FAQ     Solana     3987 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 61ms UTC 05:08 PVG 13:08 LAX 22:08 JFK 01:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86