看一个讲解 volatile 可见性教学视频的时候,发现视频中的代码和我运行的效果不太一样,有些困惑。
代码大致如下: https://gist.github.com/dsq123/e57514ca51c875b75d0ea311bb556d92
视频中运行的效果是: 1.number 字段不加 volatile,主线程的循环会一直运行,读不到 number 字段的改变。 2.而加了 volatile 后,number 字段就可见了,程序则会正常结束。
我测试的效果是,不加 volatile 关键字的情况下,主线程依旧可以获取到 AAA 线程对 number 的修改,这是为何?
1
luozic 2020-05-17 19:21:04 +08:00
System.out.println 对这个有影响
|
2
luozic 2020-05-17 19:22:34 +08:00 2
|
3
yanshenxian 2020-05-17 19:42:33 +08:00
@luozic 感觉不太对 我本地没有复现题主所说的 不加 volatile 主线程可以获取到 AAA 线程对 number 修改的情况
|
5
dengsq OP @yanshenxian 是我的疏忽,我测试时,在主线程的循环里打印了日志,所以读到了其他线程的改动。 然而我贴代码的时候,把主线程的 Sout 删掉了=。=
|
6
yanshenxian 2020-05-17 19:53:21 +08:00
@dengsq get 了
|
7
Jooooooooo 2020-05-17 20:11:42 +08:00
不写 volatile 行为不定义
|
8
dengsq OP @luozic @yanshenxian @Jooooooooo 还想请教一个问题:
有一种场景是 [A 线程指令重排导致 B 线程出错] ,如 A 改变了 boolean flag = true/false,而 B 线程需要根据 flag 处理逻辑。 既然 volatile 可以保证变量的可见性,那么不加 volatile 时,不同线程之间的变量应该是不可见的。 这样的话,也就不会出现指令重排的问题呀? |
9
Jooooooooo 2020-05-17 23:56:36 +08:00 1
@dengsq 没看懂你说的问题是啥.
"不加 volatile 时,不同线程之间的变量应该是不可见的" 这句不对. 只能说行为不定义, 可不可见取决于 cpu 的行为, 举个例子. 如果当时机器因为干别的活把当前核给让出做上下文切换了, 这个值就是可见的了 更极端的例子, 你到一个单线程的机器上跑这个代码, 不会出现不可见的问题 |
10
momocraft 2020-05-18 00:02:43 +08:00 1
保证可见的反面是 "不保证" 不是 "保证不"
|
11
dengsq OP |
12
ArronJun 2020-05-19 08:10:43 +08:00 via iPhone
打印方法加了同步关键字
|