【发布时间】:2017-07-16 22:29:02
【问题描述】:
Java 是否允许输出1, 0?我已经对其进行了非常深入的测试,但我无法获得该输出。我只得到1, 1 或0, 0 或0, 1。
public class Main {
private int x;
private volatile int g;
// Executed by thread #1
public void actor1(){
x = 1;
g = 1;
}
// Executed by thread #2
public void actor2(){
put_on_screen_without_sync(g);
put_on_screen_without_sync(x);
}
}
为什么?
在我看来,1, 0 是可能的。我的推理。
g 是易失性的,因此会确保内存顺序。所以,它看起来像:
actor1:
(1) store(x, 1)
(2) store(g, 1)
(3) memory_barrier // on x86
而且,我看到以下情况:
在store(x,1) 之前重新排序store(g, 1)(memory_barrier 在 (2) 之后)。
现在,运行线程#2。所以,g = 1, x = 0。现在,我们有了预期的输出。
我的推理有什么不正确的?
【问题讨论】:
-
println是一种同步方法 - 所以无论您要测试什么,都将从额外的同步中受益。您可能可以删除 volatile 关键字并获得相同的结果(取决于您的 CPU 等)... -
它怎么会输出
1, 0?这些字段被初始化为0,然后在稍后分配1。 -
我已经编辑以避免混淆。
-
@assylias,为什么?
-
volatile未根据内存屏障指定。如果您想深入了解volatile和一般的Java 线程同步,请阅读Java Language Specification。
标签: java volatile lock-free memory-barriers java-memory-model