Behavior of memory barrier in Java

Doug Lea is right. You can find the relevant part in section §17.4.4 of the Java Language Specification:

§17.4.4 Synchronization Order

[..] A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where “subsequent” is defined according to the synchronization order). [..]

The memory model of the concrete machine doesn’t matter, because the semantics of the Java Programming Language are defined in terms of an abstract machine — independent of the concrete machine. It’s the responsibility of the Java runtime environment to execute the code in such a way, that it complies with the guarantees given by the Java Language Specification.


Regarding the actual question:

  • If there is no further synchronization, the method read2 can print "Bar", because read2 can be executed before write.
  • If there is an additional synchronization with a CountDownLatch to make sure that read2 is executed after write, then method read2 will never print "Bar", because the synchronization with CountDownLatch removes the data race on x.

Independent volatile variables:

Does it make sense, that a write to a volatile variable does not synchronize-with a read of any other volatile variable?

Yes, it makes sense. If two threads need to interact with each other, they usually have to use the same volatile variable in order to exchange information. On the other hand, if a thread uses a volatile variable without a need for interacting with all other threads, we don’t want to pay the cost for a memory barrier.

It is actually important in practice. Let’s make an example. The following class uses a volatile member variable:

class Int {
    public volatile int value;
    public Int(int value) { this.value = value; }
}

Imagine this class is used only locally within a method. The JIT compiler can easily detect, that the object is only used within this method (Escape analysis).

public int deepThought() {
    return new Int(42).value;
}

With the above rule, the JIT compiler can remove all effects of the volatile reads and writes, because the volatile variable can not be accesses from any other thread.

This optimization actually exists in the Java JIT compiler:

  • src/share/vm/opto/memnode.cpp

Leave a Comment

tech