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

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

9852 次点击
所在节点    Java
58 条回复
vansouth
2020-07-21 10:19:00 +08:00
虽然我看得懂 但是我不喜欢这种写法
amiwrong123
2020-07-21 10:31:45 +08:00
@talen666
哪段代码,让我也康康,话说你说的是 reentrantlock 么
amiwrong123
2020-07-21 10:33:05 +08:00
@fakeshadow
额,可是三目表达式这里没涉及到 cas 啊,只有 valitale 读
amiwrong123
2020-07-21 10:34:54 +08:00
@apporoad
哈哈哈哈,老哥你挺逗
amiwrong123
2020-07-21 10:37:01 +08:00
@vansouth
本帖的主题可能要变成 简洁性 和 可读性 的争辩了。
yamasa
2020-07-21 10:57:39 +08:00
我觉得那些个 conc 包的类作者就没怎么考虑过可读性。不过 comment 倒是挺足的
zhangpeter
2020-07-21 10:59:14 +08:00
t != (t = tail)

等价于:


if (t != tail)
t = tail;
amiwrong123
2020-07-21 11:07:13 +08:00
@yamasa
嗯,好像是。尤其是无锁编程 lock free 实现的那几个类(比如那个 concurrent 跳表),不看注释根本看不懂啊
whitehack
2020-07-21 13:40:52 +08:00
```
> let t = 2
undefined
> let tail = 3
undefined
> t!=(t=tail)
true
> t
3
>

```
2kCS5c0b0ITXE5k2
2020-07-21 14:19:55 +08:00
@misaka19000

```
reduce(lambda x, y: x + y, map(lambda i: l[i] + 3, list(filter(lambda y: y % 2 == 0, range(len(l))))))
```
Boyce
2020-07-21 14:59:29 +08:00
我服了,不看评论看不懂系列。
ily433664
2020-07-21 15:18:46 +08:00
如果只一行是为了好看
p = (t != (t = tail)) ? t : hea

这种写法不是更好看
p = t != tail ? t = tail : head;

而这种可读性不是更强
p = (t != tail) ? (t = tail) : head;
atwoodSoInterest
2020-07-21 15:41:51 +08:00
@ily433664 如 TtTtTtT 大佬所言,tail 是可变的,这样的写法保证只会读取一次 tail,不会出现第二次读取值变了的情况。这是从根本上杜绝了问题的发生,而且减少了一个变量,是一个功能性的写法,不是为了炫技。
@TtTtTtT 感谢科普,又学到了新知识,真好
palmers
2020-07-21 16:16:48 +08:00
我做了一个测试, 估计大概就明白了.
```java
Object t = new Object();
Object h = new Object();
System.out.println("t: " + t);
System.out.println("h: " + h);
System.out.println("(t = h): " + (t = h));
```
forestn
2020-07-21 16:21:35 +08:00
不知道对不对 这是非阻塞算法 cas 吧
palmers
2020-07-22 09:17:31 +08:00
@palmers 我简单模拟了一下 然后反编译后字节码是这样的
源码:
```java
public void test() {
Object t = new Object();
Object h = new Object();
Object c = t != (t = h) ? t : h;
}
```
反编译后字节码:
```code
public void test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=4, args_size=1
0: new #5 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: new #5 // class java/lang/Object
11: dup
12: invokespecial #1 // Method java/lang/Object."<init>":()V
15: astore_2
16: aload_1
17: aload_2
18: dup
19: astore_1
20: if_acmpeq 27
23: aload_1
24: goto 28
27: aload_2
28: astore_3
29: return
LineNumberTable:
line 15: 0
line 16: 8
line 17: 16
line 18: 29
LocalVariableTable:
Start Length Slot Name Signature
0 30 0 this Lcom/jd/pricewarning/plussdk/worker/web/Ti;
8 22 1 t Ljava/lang/Object;
16 14 2 h Ljava/lang/Object;
29 1 3 c Ljava/lang/Object;
StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 27
locals = [ class java/lang/Object, class java/lang/Object ]
frame_type = 64 /* same_locals_1_stack_item */
stack = [ class java/lang/Object ]

```
fangcan
2020-07-22 15:44:33 +08:00
这是 cas 的体现
xiangbohua
2020-08-21 17:00:28 +08:00
“代码首先写给人看的,其次才是写给机器的” 这句话我十分的不同意,代码写出来不是让机器跑的,是让人天天朗读的,你当是编课本呢?
这句话之所以出名,是因为现在的憨憨程序员太多了,为了让后进来的倒霉蛋好接手一点,才制定的要求,提高所谓可读性(当然我自己也憨,也接手过别人的代码)。
然鹅,真正的大佬,都有种“老子就爱这么写,看不懂就别看,我的代码不需要维护!”的气概。。。(脑海浮现出 Linus Torvalds 指着你鼻子.jpg )
我是这么认为的

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

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

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

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

© 2021 V2EX