I have this simple Jcstress test:
package io.denery;
import org.openjdk.jcstress.annotations.*;
import org.openjdk.jcstress.infra.results.IIII_Result;
@JCStressTest
@Outcome(expect = Expect.ACCEPTABLE_INTERESTING)
@State
public class RaceIRIWTest {
volatile int x, y;
@Actor
public void actor1() {
x = 1;
}
@Actor
public void actor2() {
y = 1;
}
@Actor
public void actor3(IIII_Result r) {
r.r1 = x;
r.r2 = y;
}
@Actor
public void actor4(IIII_Result r) {
r.r3 = y;
r.r4 = x;
}
}
But the result of this test is:
[OK] io.denery.RaceIRIWTest (JVM args: [-XX:+UnlockDiagnosticVMOptions, -XX:+WhiteBoxAPI, -XX:-RestrictContended, -Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=en, -Duser.variant, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN]) Observed state Occurrences Expectation Interpretation
0, 0, 0, 0 22,180,923 ACCEPTABLE_INTERESTING
0, 0, 0, 1 721,581 ACCEPTABLE_INTERESTING
0, 0, 1, 0 13,347 ACCEPTABLE_INTERESTING
0, 0, 1, 1 456,971 ACCEPTABLE_INTERESTING
0, 1, 0, 0 344,068 ACCEPTABLE_INTERESTING
0, 1, 0, 1 36 ACCEPTABLE_INTERESTING
0, 1, 1, 0 528,641 ACCEPTABLE_INTERESTING
0, 1, 1, 1 258,265 ACCEPTABLE_INTERESTING
1, 0, 0, 0 204,088 ACCEPTABLE_INTERESTING
1, 0, 0, 1 667,580 ACCEPTABLE_INTERESTING
1, 0, 1, 1 94,877 ACCEPTABLE_INTERESTING
1, 1, 0, 0 663,159 ACCEPTABLE_INTERESTING
1, 1, 0, 1 306,251 ACCEPTABLE_INTERESTING
1, 1, 1, 0 128,608 ACCEPTABLE_INTERESTING
1, 1, 1, 1 18,838,186 ACCEPTABLE_INTERESTING
we see race condition, but if i put static
to volatile int x, y
and remove volatile
keyword then the result of jcstress test will be:
[OK] io.denery.RaceIRIWTest (JVM args: [-XX:+UnlockDiagnosticVMOptions, -XX:+WhiteBoxAPI, -XX:-RestrictContended, -Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=en, -Duser.variant, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN]) Observed state Occurrences Expectation Interpretation
1, 1, 1, 1 100,299,061 ACCEPTABLE_INTERESTING
Why doesn't volatile fix the race condition, but the static keyword fixes it? Or it is a Jcstress issue?
I'm not a JCStress expert.
But what you are missing is that you need to specify the legal outcomes, see the below link for an example.
[forbidden case]
In the case of the IRIW test, you want to prevent that stores made by different CPU's to different addresses, can be seen out of order. So you want to prevent that actor 3 sees r1=1, r2=0
(so sees x
before y
). And actor 4 sees r3=1, r4=0
(so sees y
before x
). So the forbidden case would be 1,0,1,0
[volatile]
When I check the results with volatile, the forbidden case is not encountered. The reason is that the example with volatile is free of data races and hence it only produces sequential consistent (SC) executions. With SC there is always some total order over the loads/stores that explains the execution. Because there is a total order, it will also order stores to different addresses issued by different CPUs. Also SC will prevent the loads being reordered since an SC execution needs to be consistent with program order (PO).
[static without volatile]
The example with the static contains a data race since there is no happens before edge between the read and the write. So with static only it is allowed to see the forbidden execution 1,0,1,0
A trivial explanation would be that the 2 loads get reordered by the JIT or CPU if it would allow for out of order loads (e.g. ARM). My guess is that you only see 1,1,1,1
because x
and y
are not unset by JCStress; but I don't know JCStress well enough.
[superfluous]
To make the example more interesting I would make the 2 stores opaque stores and the loads opaque loads and put a [LoadLoad] fence between the 2 loads to make sure they get executed in order. Opaque will make sure that the load/store don't get optimized out and it will provide atomicity (basic guarantees) but won't provide any ordering guarantees with respect to loads/stores to different addresses. So you will be testing the memory consistency guarantees of the CPU.
IRIW should not fail on modern CPUs since they are multi copy atomic, the only CPU I know of that could exhibit the behavior is the PowerPC.