Search code examples
javamultithreadingjcstress

Can JCStress outcome can be described as the result of caching instead of reordering?


I modified one of JCStress examples:

@JCStressTest
@Outcome(id = "0, 0", expect = ACCEPTABLE, desc = "Doing both reads early.")
@Outcome(id = "1, 1", expect = ACCEPTABLE, desc = "Doing both reads late.")
@Outcome(id = "1, 0", expect = ACCEPTABLE, desc = "First is visible but not second.")
@Outcome(id = "0, 1", expect = ACCEPTABLE_INTERESTING, desc = "Second is visible but not first.")
@State
public class Reordering {
    int first;
    int second;

    @Actor
    public void actor1() {
        first = 1;
        second = 1;
    }

    @Actor
    public void actor2(II_Result r) {
        r.r2 = second;
        r.r1 = first;
    }
}

which gave me the following result:

RESULT SAMPLES FREQ EXPECT DESCRIPTION
0, 0 737,822,067 26.75% Acceptable Doing both reads early.
0, 1 1,838,578 0.07% Interesting Second is visible but not first.
1, 0 13,081,701 0.47% Acceptable First is visible but not second.
1, 1 2,005,604,406 72.71% Acceptable Doing both reads late.

The Acceptable results are easy to understand but I have some questions regarding the Interesting outcome. From what I understood, JVM can optimize the code and change the order of instructions meaning the first function could roughly be translated to:

public void actor1() {
    second = 1;
    first = 1;
}

which could explain why the Interesting result was achieved. My question is: is it possible that the Interesting result was achieved not due to the code reordering done by JVM but rather by "caching" the first and not making it visible to the thread running actor2 method since the field was not a volatile one? By caching I am talking about storing it in the CPU register/store buffer and making it not visible to the other thread.


Solution

  • On the X86 stores can't be reordered with other stores and loads can't be reordered with other loads (only an older store and a newer load to a different address can be reordered). So if the compiler would not mess up the order, then on the X86 this can't fail. This is because of the strong memory model of X86: TSO (Total Store Order).

    However, if you would go for a CPU with a weaker memory model e.g. ARM or RISC-V, then such reordering could happen.