Is it true that java volatile accesses cannot be reordered?

The Java memory model provides sequential consistency (SC) for correctly synchronized programs. SC in simple terms means that if all possible executions of some program, can be explained by different executions in which all memory actions are executed in some sequential order and this order is consistent with the program order (PO) of each of the threads, then this program is consistent with these sequential executions; so it is sequential consistent (hence the name).

What this effectively means that the JIT/CPU/memory subsystem can reorder volatile writes and reads as much as it wants as long as there exists a sequential execution that could also explain the outcome of the actual execution. So the actual execution isn't that important.

If we look at the following example:

  volatile int a, b, c;            

  Thread 1                Thread 2

  a = 1;                  while (c != 1); 
  b = 1;                  print(b); 
  c = 1;               

There is a happens before relation between a=1 and b=2 (PO), and a happens before relation between c=2 and c=3 (PO) and a happens before relation c=1 and c!=0 (Volatile variable rule) and a happens before relation between c!=0 and print(b) (PO).

Since the happens before relation is transitive, there is a happens before relation between a=1 and print(b). So in that sense, it can't be reordered. However, there is nobody to prove that a reordering happened, so it can still be reordered.


What the JLS says (from JLS-8.3.1.4. volatile Fields) is, in part, that

The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).

Which means the access may be reordered, but the results of any reordering must eventually be consistent (when accessed by another thread) with the original order. A field in a single threaded application wouldn't need locking (from volatile or synchronization).