So Im experimenting a bit with multithreading currently, since im still pretty new to Java. Now, I have multiple threads that all influence the same long variable. However, it seems that afer a while of not doing anything but checking the if statement the while loop just stops executing (as in, it loops infinitely). It does work if i just print something within the while-loop.
Does not work:
while(true){
if(longVariable < 2)
break;
}
Does somehow work:
while(true){
System.out.println("hi");
if(longVariable < 2)
break;
}
Why is this?
while(true){
if(longVariable < 2)
break;
}
In this code, there is no reason for the JVM to believe that longVariable
will ever change. It can effectively rewrite it to:
long cached = longVariable;
while(true){
if(cached < 2)
break;
}
Which loops infinitely if longVariable
is at least two when it executes, because nothing can change cached
.
You have to give the compiler a hint that this rewrite isn't allowed. It works with the System.out.println
on your JVM because it happens to be implemented with synchronization (which is common, but not required). This inserts memory barriers which means that the cached value of longVariable
is invalidated, and has to be read again.
But it's not guaranteed to work. To make it work correctly, either declare the variable volatile:
volatile long longVariable
which prevents its value from being cached.
Or use something like an AtomicLong
instead of a plain long
variable.
Or, most onerously, use explicit synchronization (ensuring that all reads of and writes to the variable are synchronized on the same "something"):
long v;
synchronized (something) {
v = longVariable;
}
if (v < 2) ...