Java 多个可变变量之间的同步
鉴于以下代码:Java 多个可变变量之间的同步,java,concurrency,volatile,Java,Concurrency,Volatile,鉴于以下代码: 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 v
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
我知道对易失性变量的写入和看到更新值的读取之间存在“先发生后发生”的关系,但我觉得没有一个线程可以看到更新值,尽管我无法做到这一点。是的,这是有保证的
为了证明这一点,假设线程1打印false
,而不失一般性。由于b
是易变的,这意味着线程1在线程2写入b
之前执行打印。但是如果是这种情况,那么当线程2执行自己的打印时,a
必须已经被线程1设置为true
请注意,在写入之前,无法按照以下要求对打印进行重新排序:
- 如果x和y是同一线程的动作,并且x在程序顺序中位于y之前,那么hb(x,y)[x发生在y之前]
a
或b
的写入将立即对另一个线程可见:
- 对
字段()的写入发生在随后每次读取该字段之前volatile
我认为它必须至少打印一个
true
,尽管我实际上不会编写这样的代码。如果one
打印false
,则必须已执行a=true
,因此另一个线程必须打印true
。如果两个线程交错,它们都可以打印true
,但我看不到一个路径可以同时打印false
。我看不到这里的冲突。这两种方法都无法锁定,因为易失性变量将被简单地更新和释放,例如,一旦b=true
完成,它将释放b上的锁,而不是在等待a被释放时保留它。我认为您的问题可能会得到回答。这不是背负。我认为这里的关键是println
是否可以在volatile赋值之上重新排序,我认为答案是“否”。这就是我要说的。问题是,程序顺序是有保证的,只允许不违反程序顺序相同结果的重新排序。因为在这里重新排序会产生不同的结果,我认为这是不允许的。不过,我想在内存模型中找到一个更明确的规则@AndyTurner你能澄清17.4.5中的哪一位表示它们不能被重新排序吗?@AndyTurner只是加了一个引号。“对易失性字段(§8.3.1.4)的写入发生在该字段的每次后续读取之前。”这并没有说明对字段的写入发生在读取另一个字段之前。同样在17.4.5中:“需要注意的是,两个动作之间的“发生在之前”关系的存在并不一定意味着它们必须在实现中以该顺序发生。”“如果x和y是同一线程的动作,并且x在程序顺序中位于y之前,那么hb(x,y)[x发生在y之前]。”我想这就是我遗漏的部分。