Java Memory Model and happens-before
Good afternoon. There is a small question about JMM. I know how happens-before works, but I can't understand one point. 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 there is some rule to determine this?
2 answers
If we draw the execution threads in your code, we get this picture:
Main thread is the main thread of your program, Thread1 is the thread that you explicitly create.
Writing and reading the volatile variable flag
actually creates a Happens-Before relationship (E → B in the diagram). Thus, with respect to the call System.out.println(x);
, we have two execution threads, for each of which the execution order is guaranteed: A → B → C and D → E → B → C. Writing to the x
variable is guaranteed to occur before it is read.
But here are the instructions for writing to the variable x
(A and D) are in the 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 may well execute the instructions as follows:
We don't know what value the System.out.println(x);
statement will see for several reasons:
A thread can read a value set in it ( whether it was set earlier or later than another thread) or a value set in another thread. Since there are no guarantees on what value the stream will read.
Since it is not possible to determine the execution time of an instruction in different threads relative to other threads-unknown at what point will the threads execute the instructions
x = 10
andflag = true
relative to each other.
Relative to happens-before happens with the volatile
variable.
In this case, if the volatile
variable is read after its variable is written, then the read operation will NECESSARILY 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 about that, we do not know when the flag = true
instruction will be executed, it can be executed either before or after reading (one or more) values from the volatile
variable in the generated thread.
It should be noted that the relation shown in the picture in the Nofate response should not be interpreted as a mandatory order by induction or blocking the reader until the value of the volatile
variable is set.
" Writing to variable x is guaranteed to happen sooner her readings. "
The thread will simply be in an infinite loop until flag = true
is executed.