为什么 JMM 产生 (0, 0) 即使它被认为是禁止的结果
Why JMM produces (0, 0) even though it is considered a forbidden result
我正在检查 JMM 的一些语句,并且我编写了一个 JCS 测试,如下所示:
@JCStressTest
@State
@Outcome(expect = ACCEPTABLE, desc = "ACCEPTABLE")
public class ConcurrencyTest {
private final int a = 1;
private final int b = 2;
public ConcurrencyTest instance;
@Actor
public void actor1() {
instance = new ConcurrencyTest();
}
@Actor
public void actor2(II_Result result) {
ConcurrencyTest c = instance;
if (c != null) {
result.r1 = c.a;
result.r2 = c.b;
}
}
}
在运行这个测试之后,我看到了以下结果:
(0, 0) (1, 2)
尽管 JMM 明确指出结果 (0, 0) 是禁止的,但为什么会这样?
让我们稍微更改一下代码:
@JCStressTest
@State
@Outcome(id = "0, 0", expect = Expect.FORBIDDEN)
@Outcome(id = "1, 2", expect = Expect.ACCEPTABLE)
@Outcome(id = "-1, -1", expect = Expect.ACCEPTABLE)
public class ConcurrencyTest {
private final int a = 1;
private final int b = 2;
public ConcurrencyTest instance;
@Actor
public void actor1() {
instance = new ConcurrencyTest();
}
@Actor
public void actor2(II_Result result) {
ConcurrencyTest c = instance;
if (c != null) {
result.r1 = c.a;
result.r2 = c.b;
} else { // <-- this is what you care about
result.r1 = -1;
result.r2 = -1;
}
}
}
您认为 @Outcome(id = "0, 0")
中的值来自哪里?这些是您在 II_Result
中设置的,其中包含两个 int
,默认值为 0
。
这样,当c == null
(意思是actor1
没有运行)时,if (c != null) { ...
将不会被输入。因此,在您的代码中,您什么都不做:导致 r1
和 r2
的默认值为零。您应该像我一样通过简单的 else
来处理这种默认情况。
我正在检查 JMM 的一些语句,并且我编写了一个 JCS 测试,如下所示:
@JCStressTest
@State
@Outcome(expect = ACCEPTABLE, desc = "ACCEPTABLE")
public class ConcurrencyTest {
private final int a = 1;
private final int b = 2;
public ConcurrencyTest instance;
@Actor
public void actor1() {
instance = new ConcurrencyTest();
}
@Actor
public void actor2(II_Result result) {
ConcurrencyTest c = instance;
if (c != null) {
result.r1 = c.a;
result.r2 = c.b;
}
}
}
在运行这个测试之后,我看到了以下结果:
(0, 0) (1, 2)
尽管 JMM 明确指出结果 (0, 0) 是禁止的,但为什么会这样?
让我们稍微更改一下代码:
@JCStressTest
@State
@Outcome(id = "0, 0", expect = Expect.FORBIDDEN)
@Outcome(id = "1, 2", expect = Expect.ACCEPTABLE)
@Outcome(id = "-1, -1", expect = Expect.ACCEPTABLE)
public class ConcurrencyTest {
private final int a = 1;
private final int b = 2;
public ConcurrencyTest instance;
@Actor
public void actor1() {
instance = new ConcurrencyTest();
}
@Actor
public void actor2(II_Result result) {
ConcurrencyTest c = instance;
if (c != null) {
result.r1 = c.a;
result.r2 = c.b;
} else { // <-- this is what you care about
result.r1 = -1;
result.r2 = -1;
}
}
}
您认为 @Outcome(id = "0, 0")
中的值来自哪里?这些是您在 II_Result
中设置的,其中包含两个 int
,默认值为 0
。
这样,当c == null
(意思是actor1
没有运行)时,if (c != null) { ...
将不会被输入。因此,在您的代码中,您什么都不做:导致 r1
和 r2
的默认值为零。您应该像我一样通过简单的 else
来处理这种默认情况。