Good day. There is a small question on JMM. I know how it happens-before, but I can not understand one thing. Here is the code:

private static int x = 0; private static volatile boolean flag = false; public static void main(String[] args) throws InterruptedException { new Thread(() -> { x = 10; while (!flag) ; System.out.println(x); }).start(); x = 5; flag = true; } 

What value should X take? If some rule to define it?

  • Any of the proposed. The order of assignments 5 and 10 is not defined, it can be any, the generated thread can start work earlier than x = 5 and vice versa. As far as I understand, happens-before in this case applies only to the flag , so two different threads can exist with different values ​​.. - etki
  • Yes, I also think that it can be either 5 or 10. BUT if you take the JMM theory, then just reading flag variable in stream 2 (not main) means that the transitive closure and the order is complete!, That is: 1) x = 5; 2) flag = true; 3) while (! Flag) 4) System.out.println (x); But how does x = 10 relate to this order; I can not understand, because inside the stream, too, the order is complete. It turns out 2 complete orders merge somehow? - slippery
  • reading the flag variable only affects the visibility of the flag variable - etki

2 answers 2

If you portray the execution threads in your code, we get the following picture:

enter image description here

Main thread is the main thread of your program, Thread1 is a thread that you explicitly create.

Writing and reading the volatile variable flag really creates a Happens-Before relationship ( E β†’ B in the diagram). So with respect to calling System.out.println(x); we have two execution threads, for each of which the order of execution is guaranteed: A β†’ B β†’ C and D β†’ E β†’ B β†’ C. Writing to the variable x guaranteed to happen before it is read.

But the instructions for writing to the variable x ( A and D ) are in a race condition and their order of execution relative to each other is not defined. As a result, what we see in the diagram can not be called a complete order. The JVM can easily execute the instructions as follows:

enter image description here

  • "Writing to the x variable is guaranteed to happen before reading it." this sentence is read as if one thread will be suspended until the second installs new knowledge - but this is not so. - Mikhailov Valentine
  • @MikhailovValentine and here, no matter which thread sets the value first, it’s still going to happen after both entries - etki
  • @Etki, yes, that's right, I wanted to point to another implementation of D β†’ E β†’ B β†’ C, which will not necessarily be the case. it is possible that D β†’ E will happen first and then A β†’ B β†’ C and in this case the diagram will have a different look. - Mikhailov Valentine
  • one
    @MikhailovValentine yes all the same. The arrow between the two threads simply shows that operation B must occur after operation A. The order of the remaining operations between threads is not defined, this diagram is quite readable as DEABC. - etki
  • @Etki, thanks for the apologetics. everything is exactly like this - Nofate ♦

We do not know what value the System.out.println(x); instruction will see System.out.println(x); for several reasons:

  • A thread can read the value set in it (regardless of whether it was set earlier or later of another thread) or the value set in another thread. Since there is no guarantee what value the stream will read.

  • In view of the fact that it is impossible to determine the execution time of an instruction in different threads relative to other threads - it is not known at what point the threads will execute instructions x = 10 and flag = true relative to each other.

Relatively happens-before what happens with a volatile variable. In this case, if the reading of a volatile variable occurs after writing it to a variable, then the read operation MUST be able to see the β€œnew” data. In this case, it only tells us that the thread that is in the loop will exit it as soon as the flag = true instruction is executed. But again, we don’t know when flag = true will be executed; it can be executed either before or after reading (one or several) values ​​from a volatile variable in the spawned thread.

It should be noted that the relation depicted in the picture in the Nofate answer should not be interpreted as a mandatory procedure by induction or locking the reader until the value of the volatile variable is set.

β€œWriting to the variable x is guaranteed to happen before reading it.”

The stream will simply be in an infinite loop until flag = true .