请教一个 Java volatile 字段可见性的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
beixun
V2EX    Java

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

  •  
  •   beixun 2020 年 5 月 17 日 3092 次点击
    这是一个创建于 2073 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

    更极端的例子, 你到一个单线程的机器上跑这个代码, 不会出现不可见的问题
    momocraft
        10
    momocraft  
       2020 年 5 月 18 日   1
    保证可见的反面是 "不保证" 不是 "保证不"
    beixun
        11
    beixun  
    OP
       2020 年 5 月 18 日
    @Jooooooooo @momocraft 结合二位的回答我就明白了,是我的理解有问题,取反取错了。
    非常感谢
    ArronJun
        12
    ArronJun  
       2020 年 5 月 19 日 via iPhone
    打印方法加了同步关键字
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5396 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 07:44 PVG 15:44 LAX 23:44 JFK 02:44
    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