阅读时this blog post我无法理解第 3.6 和 3.7 节。
3.6 中的代码:
@JCStressTest
@State
public class AcquireOrderWrong {
int x;
volatile int g;
@Actor
public void actor1() {
g = 1;
x = 1;
}
@Actor
public void actor2(IntResult2 r) {
r.r1 = x;
r.r2 = g;
}
}
3.7 中的代码:
@JCStressTest
@Outcome(id = "1, 0", expect = Expect.FORBIDDEN, desc = "Happens-before violation")
@Outcome( expect = Expect.ACCEPTABLE, desc = "All other cases are acceptable.")
@State
public class SafePublication {
int x;
volatile int ready;
@Actor
public void actor1() {
x = 1;
ready = 1;
}
@Actor
public void actor2(IntResult2 r) {
r.r1 = ready;
r.r2 = x;
}
}
在 3.6 中,据说 1,0 是一个不可能的结果,因为这是一场赤裸裸的数据竞争,我(可能错误地)将其解释为,因为不相关的操作可以是在执行时重新排序可能会发生这种情况。
但如果是这样的话,3.7 中的示例不应该遇到同样的问题吗?
最佳答案
根据 doc,在 3.7 中,ready
是一个 volatile
变量。
This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
在actor()
中,您在设置x
之后设置ready
。因此,当您在方法actor2
中读取ready
时,JVM可以保证x=1
也是可见的,这避免了(1, 0)
作为输出。
关于java - 在java中同时访问 volatile 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48851817/