Today I read java interview questions and I read this question: Question : Consider the following Java code snippet, which is initializing two variables and both are not volatile, and two threads T1 and T2 are modifying these values as following, both are not synchronized
int x = 0;
boolean bExit = false;
Thread 1 (not synchronized)
x = 1;
bExit = true;
Thread 2 (not synchronized)
if (bExit == true)
System.out.println("x=" + x);
Now tell us, is it possible for Thread 2 to print “x=0”?
So, the answer is "yes". In the explanation there is "because without any instruction to compiler e.g. synchronized or volatile, bExit=true might come before x=1 in compiler reordering." Before that I don't know that the compiler can execute one line before another line after it.
Why is this reordering ? And what if I print something to the console from different thread - the line that is supposed to be print first will be print after the line that is supposed to be print second (if they are printed from the same thread) ? It's weird to me (maybe, because I saw this thing for reordering for the first time). Can someone give some explanation ?
The JIT compiler* can change the order of execution if it won't change the result according to the Java standard. Switching
x = 1;
bExit = true;
to
bExit = true;
x = 1;
does not change the result because there is no synchronization, ie. according to the standard, these variables should not be read by another thread while doing this, and neither of these statements need the other variable. (On modern CPUs, both commands will in fact be executed at the same time which of course means it is unspecified which will be changed first.)
Not only reordering can cause that behavior. It may happen that bExit
can be in one memory page and x
in another and if the application is running on a multi-processor (or multi-core) system, then without synchronization, it can happen that memory page with bExit
will be committed (and changes to it will be visible in all other cores) before memory page with x
.
*Edit: Java compiler (compiling .java into .class) cannot change in-thread execution order but JIT compiler (compiling .class into binary code) can. However Java compiler can omit some statements if it thinks they are redundant, eg.
x = 1;
bExit = true;
x = 2;
can optimize away x = 1;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With