在 java 中并发访问 volatile 变量
Accessing volatile varibales concurrently in java
在阅读 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 中的示例不应该遇到同样的问题吗?
在3.7中,ready
是一个volatile
变量,根据doc
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)
作为输出。
在阅读 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 中的示例不应该遇到同样的问题吗?
在3.7中,ready
是一个volatile
变量,根据doc
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)
作为输出。