考虑这些指示两个不同任务完成的共享标志:
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的定义中找到它:
- 线程中的每个操作都发生在该线程中的每个后续操作之前。
- 监视器上的解锁发生在该监视器上的每个后续锁定之前。
- 对 volatile 字段的写入发生在该 volatile 字段的每次后续读取之前。
最后一句中没有提到线程关系,因此我认为它在所有线程中都有效。
最佳答案
首先代码可以简化如下:
第一:
completed1 = true;
if (completed2) continueSomeOtherStuff();
第二:
completed2 = true;
if (completed1) continueSomeOtherStuff();
不改变行为,因为删除的变量只能由修改它们的线程读取,所以它们始终为真。
由于您已将变量声明为 volatile
,Java 内存模型保证每个线程立即“看到”其他线程的修改。这意味着所有缓存都必须失效,并且不允许 JVM 编译器重新排序或优化这些变量的读取。
因此,在您的情况下,可以保证 continueSomeOtherStuff()
方法至少被调用一次。它也可以被调用两次,在极少数情况下,两个线程都在评估条件之前执行了第一个赋值。
关于java - 仅使用 volatile 检查并行完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40940318/