给出以下代码:
public class Test {
private volatile boolean a;
private volatile boolean b;
private void one () {
a = true;
System.out.println (b);
}
private void two () {
b = true;
System.out.println (a);
}
public static void main (String[] args) throws Exception {
Test s = new Test ();
Thread one = new Thread (s::one);
Thread two = new Thread (s::two);
one.start ();
two.start ();
one.join ();
two.join ();
}
}
(在Java内存模型下)是否保证至少一个线程会打印true
?
我知道对volatile变量的写入与看到更新值的读取之间存在事前发生的关系,但是看来我没有一个线程可以看到更新后的值,尽管我无法不可能实现。
答案 0 :(得分:4)
是的,可以保证。
为证明这一点,在不失一般性的前提下,假设线程1打印false
。由于b
是易失性的,这意味着线程1在线程2写入b
之前执行了打印。但是如果是这种情况,那么到线程2执行自己的打印时,a
必须已经被线程1设置为true
。
请注意,根据JLS §17.4.5,在写之前无法重新排序打印件:
- 如果 x 和 y 是同一线程的动作,并且 x 按照程序顺序排在 y 之前,然后 hb(x,y) [ x 发生在 y ]之前。
此外,对a
或b
的写入将立即对其他线程可见:
- 在随后每次对该字段进行读取之前,都会对
volatile
字段(§8.3.1.4)进行写操作。