Search code examples
javamultithreadingconcurrencyvolatile

Accessing volatile varibales concurrently in java


While reading this blog post I'm failing to understand section 3.6 and 3.7.

Code in 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;
    }
}

Code in 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;
    }
}

In 3.6 it's say that 1,0 is an impossibile outcome due to it is a naked data race which I (maybe wrongly) interpret as due to the fact that unrelated operations can be reordered on execution this could happend.

But if this is the case shouldn't the example in 3.7 suffer of the same problem ?


Solution

  • In 3.7, ready is a volatile variable, according to the doc

    This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.

    In actor(), you set ready after setting x. So, when you read ready in method actor2, JVM can gurantee that x=1 is also visible, which avoids (1, 0) as output.