仅使用 volatile 检查并行完成
checking for parallel completion using volatile only
考虑这些指示两个不同任务完成的共享标志:
volatile boolean completed1 = false;
volatile boolean completed2 = false;
现在考虑两个线程:
没有。 1:
completed1 = true;
if (completed1 && completed2) continueSomeOtherStuff();
没有。 2:
completed2 = true;
if (completed1 && completed2) continueSomeOtherStuff();
continueSomeOtherStuff() 是否会被可靠地至少调用一次?
更新:
在http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf中happens-before的定义中找到:
- 一个线程中的每个动作先于该线程中的每个后续动作。
- 监视器上的解锁发生在该监视器上的每个后续锁定之前。
- 对易失性字段的写入发生在每次后续读取该易失性字段之前。
最后一句话中没有提到线程关系,所以我认为它对所有线程都有效。
首先代码可以简化如下:
No1:
completed1 = true;
if (completed2) continueSomeOtherStuff();
No2:
completed2 = true;
if (completed1) continueSomeOtherStuff();
不改变行为,因为删除的变量仅由修改它们的线程读取,所以它们始终为真。
由于您已将变量声明为 volatile
,因此 Java 内存模型保证每个线程立即被其他线程 'sees' 修改。这意味着必须使所有缓存失效,并且不允许 JVM 编译器重新排序或优化这些变量的读取。
因此在您的情况下,可以保证 continueSomeOtherStuff()
方法至少被调用一次。它也可以被调用两次,在极少数情况下,两个线程都在评估条件之前执行了他们的第一个赋值。
考虑这些指示两个不同任务完成的共享标志:
volatile boolean completed1 = false;
volatile boolean completed2 = false;
现在考虑两个线程:
没有。 1:
completed1 = true;
if (completed1 && completed2) continueSomeOtherStuff();
没有。 2:
completed2 = true;
if (completed1 && completed2) continueSomeOtherStuff();
continueSomeOtherStuff() 是否会被可靠地至少调用一次?
更新:
在http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf中happens-before的定义中找到:
- 一个线程中的每个动作先于该线程中的每个后续动作。
- 监视器上的解锁发生在该监视器上的每个后续锁定之前。
- 对易失性字段的写入发生在每次后续读取该易失性字段之前。
最后一句话中没有提到线程关系,所以我认为它对所有线程都有效。
首先代码可以简化如下:
No1:
completed1 = true;
if (completed2) continueSomeOtherStuff();
No2:
completed2 = true;
if (completed1) continueSomeOtherStuff();
不改变行为,因为删除的变量仅由修改它们的线程读取,所以它们始终为真。
由于您已将变量声明为 volatile
,因此 Java 内存模型保证每个线程立即被其他线程 'sees' 修改。这意味着必须使所有缓存失效,并且不允许 JVM 编译器重新排序或优化这些变量的读取。
因此在您的情况下,可以保证 continueSomeOtherStuff()
方法至少被调用一次。它也可以被调用两次,在极少数情况下,两个线程都在评估条件之前执行了他们的第一个赋值。