@JCStressTest
@State
@Outcome(id = "10", expect = ACCEPTABLE, desc = "Boring")
@Outcome(id = {"0", "1"}, expect = FORBIDDEN, desc = "Boring")
@Outcome(id = {"9", "8", "7", "6", "5"}, expect = ACCEPTABLE, desc = "Okay")
@Outcome( expect = ACCEPTABLE_INTERESTING, desc = "Whoa")
public static class Volatiles {
volatile int x;
@Actor
void actor1() {
for (int i = 0; i < 5; i++) {
x++;
}
}
@Actor
void actor2() {
for (int i = 0; i < 5; i++) {
x++;
}
}
@Arbiter
public void arbiter(I_Result r) {
r.r1 = x;
}
}
作者强调,由于增量不是原子操作,所以不能指望每次循环迭代只会"丢失"一个增量更新.因此,除了0
和1
之外,所有的结果(最多10
个)都是允许的(并且确实发生了).
我明白为什么不允许0
了:正如JLS中所述,在对象的缺省值的初始化和每个线程中的第一个操作之间存在HB边缘.
JLS 17.4.4个
将缺省值(零、假或空)写入每个变量会与每个线程中的第一个操作同步.
作者还解释了如何获得结果2
:
The most interesting result, "2" can be explained by this interleaving:
Thread 1: (0 ------ stalled -------> 1) (1->2)(2->3)(3->4)(4->5)
Thread 2: (0->1)(1->2)(2->3)(3->4) (1 -------- stalled ---------> 2)
我理解你不能像这样"延伸"上面的解释:
Thread 1: (0 --------- stalled -----------> 1) (1->2)(2->3)(3->4)(4->5)
Thread 2: (0->1)(1->2)(2->3)(3->4)(4->5)
因为它会导致结果5
.
但是,难道不存在一个可以产生1
的死刑吗?
我绝对想不出有什么.但为什么真的没有呢?