我现在连个三目表达式都看不懂了…

2020-07-20 12:01:50 +08:00
 amiwrong123

ConcurrentLinkedQueue 的 offer 方法有个奇怪的三目表达式

*/
    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) {
                // p is last node
                if (p.casNext(null, newNode)) {
                    // Successful CAS is the linearization point
                    // for e to become an element of this queue,
                    // and for newNode to become "live".
                    if (p != t) // hop two nodes at a time
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            else if (p == q)
                // We have fallen off list.  If tail is unchanged, it
                // will also be off-list, in which case we need to
                // jump to head, from which all live nodes are always
                // reachable.  Else the new tail is a better bet.
                p = (t != (t = tail)) ? t : head;
            else
                // Check for tail updates after two hops.
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

这个三目表达式(t != (t = tail)) ? t : head;的左边看起来很奇怪,(t != (t = tail))本质上不就是(t != t)吗,那这不是肯定不成立吗?我佛了

jdk8

9850 次点击
所在节点    Java
58 条回复
szzhiyang
2020-07-20 18:13:50 +08:00
Go 代码就不会有这样晦涩难懂的表达。
amiwrong123
2020-07-20 18:14:06 +08:00
@yyyyfan
原来是这样的吗。可是看作者就是 Doug Lea 啊
amiwrong123
2020-07-20 18:31:26 +08:00
@szzhiyang
原来这就是 go 吗,爱了爱了
TtTtTtT
2020-07-20 20:24:46 +08:00
@chairuosen 正因为这不是业务代码,所以才要剩下一个 slots.
TtTtTtT
2020-07-20 20:27:40 +08:00
@xiangyuecn 不对,因为 tail 是个 mutable 的,所以每次拿的时候就要存下来,否则就会存在变化的可能。
你可以用一个新的 ref 去引用你新拿到的 tail,但是如前所说会多一个 slot 。

p = (t != (t = tail)) ? t : head;

等价于:

val tmpT = tail;
p = t != tmpT ? tmpT : head;
t = tmpT;
TtTtTtT
2020-07-20 20:29:28 +08:00
@szzhiyang 因为 JVM 字节码有解释器模型。。而 Go,不是也有 interface{}的 magic 嘛~
Jooooooooo
2020-07-20 20:29:35 +08:00
质疑别人无所谓, 但是质疑 Doug Lea 需要更多的证据.
tikazyq
2020-07-20 21:20:32 +08:00
这种代码是确定没有人质疑它的可读性?
misaka19000
2020-07-20 21:31:22 +08:00
@xiangyuecn #14 多写一行不觉得很丑吗?
misaka19000
2020-07-20 21:33:13 +08:00
这种代码和业务代码不一样,这种代码一旦写好基本上不存在修改的可能,所以可以降低可读性来提高代码的简洁性。
786375312123
2020-07-20 21:34:11 +08:00
代码写的不好,和三目运算符没关系
786375312123
2020-07-20 21:34:41 +08:00
@misaka19000 代码简洁的目的是什么?
misaka19000
2020-07-20 21:37:32 +08:00
@786375312123 #31 好看啊,能写一行的为啥要花两行来写
786375312123
2020-07-20 21:38:52 +08:00
@misaka19000 好看有啥用?
misaka19000
2020-07-20 21:48:10 +08:00
@786375312123 #33 你要这么说那我无话可说,人各有志
786375312123
2020-07-20 21:49:36 +08:00
@misaka19000 不是,我就是好奇,这种“一行比两行好的好看”,有啥用?
talen666
2020-07-20 22:05:51 +08:00
这不是 Lock 锁的核心代码吗~当时看的时候,也是迷糊了一会。按照括号来,后来看懂了
fakeshadow
2020-07-20 22:19:01 +08:00
没写过 java,但是 cas 操作这么写很可能是有原因的。memory order 和 race 问题你用一般业务的写法有时反而更难懂
apporoad
2020-07-21 04:47:38 +08:00
代码自带混淆
acainiao
2020-07-21 09:17:43 +08:00
@TtTtTtT 代码这么写是禁忌吧

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

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

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

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

© 2021 V2EX