在阅读这篇博客文章时,我没有理解第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中的例子难道不应该遇到同样的问题吗?
发布于 2018-02-18 13:00:54
在3.7中,ready是一个volatile变量,根据文档
这意味着对易失性变量的更改对其他线程总是可见的。此外,它还意味着当线程读取易失性变量时,它不仅会看到对易失性的最新更改,而且还会看到导致更改的代码的副作用。
在actor()中,在设置x之后设置ready。因此,当您在方法ready中读取actor2时,JVM可以保证x=1也是可见的,这避免了(1, 0)作为输出。
https://stackoverflow.com/questions/48851817
复制相似问题