Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java memory model: volatile variables and happens-before

I'd like to clarify how happens-before relation works with volatile variables. Let we have the following variables:

public static int i, iDst, vDst; public static volatile int v; 

and thread A:

i = 1; v = 2; 

and thread B:

vDst = v; iDst = i; 

Are the following statements correct in accordance with Java memory model (JMM)? If not, what would be correct interpretation?

  • i = 1 always happens-before v = 2
  • v = 2 happens-before vDst = v in JMM only if it's actually happens before in time
  • i = 1 happens-before iDst = i in JMM (and iDst will be predictably assigned 1) if v = 2 actually happens before vDst = v in time
  • Otherwise order between i = 1 and iDst = i is undefined and resulting value of iDst is undefined as well

Mistake in the logic:

There is no "wall clock time" concept in JMM, and we should rely on synchronization order as an ordering guide for v = 2 and vDst = v. See the chosen answer for further details.

like image 436
Alexey Avatar asked May 14 '15 19:05

Alexey


People also ask

What will happen if we declare the variable as volatile in Java?

For Java, “volatile” tells the compiler that the value of a variable must never be cached as its value may change outside of the scope of the program itself.

What is happens before rule in JVM?

The Java happens before guarantee is a set of rules that govern how the Java VM and CPU is allowed to reorder instructions for performance gains.

How does volatile variable works in Java?

The volatile modifier is used to let the JVM know that a thread accessing the variable must always merge its own private copy of the variable with the master copy in the memory. Accessing a volatile variable synchronizes all the cached copied of the variables in the main memory.

Where are volatile variables stored Java memory?

Volatile fields are instance or class (static) variables and are stored in the heap.


2 Answers

  • i = 1 always happens-before v = 2

True. By JLS section 17.4.5,

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).


  • v = 2 happens-before vDst = v in JMM only if it's actually happens before in time
  • i = 1 happens-before iDst = i in JMM (and iDst will be predictably assigned 1) if v = 2 actually happens before vDst = v in time

False. The happens-before order does not make guarantees about things happening before each other in physical time. From the same section of the JLS,

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

It is, however, guaranteed that v = 2 happens-before vDst = v and i = 1 happens-before iDst = i if v = 2 comes before vDst = v in the synchronization order, a total order over the synchronization actions of an execution that is often mistaken for the real-time order.


  • Otherwise order between i = 1 and iDst = i is undefined and resulting value of iDst is undefined as well

This is the case if vDst = v comes before v = 2 in the synchronization order, but actual time doesn't come into it.

like image 74
user2357112 supports Monica Avatar answered Sep 19 '22 19:09

user2357112 supports Monica


Yes all of them are correct according to this section about happens-before order:

  1. i = 1 always happens-before v = 2 since:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

  1. v = 2 happens-before vDst = v in JMM only if it's actually happens before in time, since v is volatile, and

A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.

  1. i = 1 happens-before iDst = i in JMM (and iDst will be predictably assigned 1) if v = 2 actually happens before vDst = v in time. This is because in this case:
    • i = 1 happens-before v = 2
    • v = 2 happens-before vDst = v
    • vDst = v happens-before iDst = i

If hb(x, y) and hb(y, z), then hb(x, z).

EDIT:

As argued by @user2357112, it seems statements 2 and 3 are not accurately correct. The happens-before relationship does not necessarily impose a timing order between actions having this relationship, as mentioned in the same section of the JLS:

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

Therefore, in terms of the rules mentioned in the JLS, we shouldn't make assumptions on the actual timing of the execution of the statements.

like image 33
M A Avatar answered Sep 18 '22 19:09

M A