beixun
V2EX  ›  Java

请教一个 Java volatile 字段可见性的问题

  •  
  •   beixun · May 17, 2020 · 3307 views
    This topic created in 2193 days ago, the information mentioned may be changed or developed.

    看一个讲解 volatile 可见性教学视频的时候,发现视频中的代码和我运行的效果不太一样,有些困惑。

    代码大致如下: https://gist.github.com/dsq123/e57514ca51c875b75d0ea311bb556d92

    视频中运行的效果是: 1.number 字段不加 volatile,主线程的循环会一直运行,读不到 number 字段的改变。 2.而加了 volatile 后,number 字段就可见了,程序则会正常结束。

    我测试的效果是,不加 volatile 关键字的情况下,主线程依旧可以获取到 AAA 线程对 number 的修改,这是为何?

    Supplement 1  ·  May 17, 2020
    测试时在主线程里面打印了日志,所以才出现了此问题。现在搞清楚了,感谢一楼大哥
    while (mt.number == 0) {
    // System.out.println...
    }
    12 replies    2020-05-19 08:10:43 +08:00
    luozic
        1
    luozic  
       May 17, 2020
    System.out.println 对这个有影响
    luozic
        2
    luozic  
       May 17, 2020   ❤️ 2
    yanshenxian
        3
    yanshenxian  
       May 17, 2020
    @luozic 感觉不太对 我本地没有复现题主所说的 不加 volatile 主线程可以获取到 AAA 线程对 number 修改的情况
    beixun
        4
    beixun  
    OP
       May 17, 2020
    @luozic 确实是这样,是 System.out.println 所影响的。
    beixun
        5
    beixun  
    OP
       May 17, 2020
    @yanshenxian 是我的疏忽,我测试时,在主线程的循环里打印了日志,所以读到了其他线程的改动。 然而我贴代码的时候,把主线程的 Sout 删掉了=。=
    yanshenxian
        6
    yanshenxian  
       May 17, 2020
    @dengsq get 了
    Jooooooooo
        7
    Jooooooooo  
       May 17, 2020
    不写 volatile 行为不定义
    beixun
        8
    beixun  
    OP
       May 17, 2020
    @luozic @yanshenxian @Jooooooooo 还想请教一个问题:
    有一种场景是 [A 线程指令重排导致 B 线程出错] ,如 A 改变了 boolean flag = true/false,而 B 线程需要根据 flag 处理逻辑。

    既然 volatile 可以保证变量的可见性,那么不加 volatile 时,不同线程之间的变量应该是不可见的。

    这样的话,也就不会出现指令重排的问题呀?
    Jooooooooo
        9
    Jooooooooo  
       May 17, 2020   ❤️ 1
    @dengsq 没看懂你说的问题是啥.

    "不加 volatile 时,不同线程之间的变量应该是不可见的" 这句不对. 只能说行为不定义, 可不可见取决于 cpu 的行为, 举个例子. 如果当时机器因为干别的活把当前核给让出做上下文切换了, 这个值就是可见的了

    更极端的例子, 你到一个单线程的机器上跑这个代码, 不会出现不可见的问题
    momocraft
        10
    momocraft  
       May 18, 2020   ❤️ 1
    保证可见的反面是 "不保证" 不是 "保证不"
    beixun
        11
    beixun  
    OP
       May 18, 2020
    @Jooooooooo @momocraft 结合二位的回答我就明白了,是我的理解有问题,取反取错了。
    非常感谢😄
    ArronJun
        12
    ArronJun  
       May 19, 2020 via iPhone
    打印方法加了同步关键字
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5696 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 03:22 · PVG 11:22 · LAX 20:22 · JFK 23:22
    ♥ Do have faith in what you're doing.