Behavior of memory barrier in Java Behavior of memory barrier in Java multithreading multithreading

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:


As far as I understood the question is actually about volatile read/writes and its happens-before guarantees. Speaking of that part, I have only one thing to add to nosid's answer:

Volatile writes cannot be moved before normal writes, volatile reads cannot be moved after normal reads. That's why read1() and read2() results will be as nosid wrote.

Speaking about barriers - the defininition sounds fine for me, but the one thing that probably confused you is that these are things/tools/way to/mechanism (call it whatever you like) to implement behavior described in JMM in hotspot. When using Java, you should rely on JMM guarantees, not implementation details.