Reputation: 115
I'm new to java concurrent coding and encounter an issue. The following code cannot stop while it runs. Who can tell me why? Thanks
import java.util.concurrent.TimeUnit;
public class Test {
private static boolean stop;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println(Thread.currentThread());
System.out.println(stop);
while (!stop) {
}
}).start();
TimeUnit.SECONDS.sleep(1);
stop = true;
System.out.println(Thread.currentThread());
System.out.println(stop);
}
}
I also try to run the following code and it can stop. Who can tell me why? Thanks
import java.util.concurrent.TimeUnit;
public class Test {
private static boolean stop;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println(Thread.currentThread());
System.out.println(stop);
while (!stop) {
System.out.println(" ");
}
}).start();
TimeUnit.SECONDS.sleep(1);
stop = true;
System.out.println(Thread.currentThread());
System.out.println(stop);
}
}
Upvotes: 2
Views: 103
Reputation: 140318
Because you've not indicated to the compiler that stop
might be changed and read by multiple threads:
private static boolean stop;
it is allowed to optimize this:
while (!stop) {
}
to
if (!stop) {
while (true) {
}
}
which will never stop if stop
is initially false.
Declaring stop
volatile
:
private static volatile boolean stop;
disallows this optimization.
Upvotes: 8
Reputation: 1790
JVM typically optimizes your code before actually executing it. In your case, while(!stop){}
gets optimized to while(true){}
. This happens because you aren't explicitly accessing your static variable via synchronized function, and JVM assumes the variable won't change in Thread unsafe manner.
To avoid the optimization, place anything in your while loop. You could do something like:
while(!stop) {
try{
Thread.sleep(1); // You could also call any other function here.
}
catch(Exception e) { }
}
In this case, JVM wouldn't try to optimize, and your code will execute as expected.
EDIT:
While this does work currently, but based on comments, I concur that this can change in future versions (or in other parallel implementations of JDK/JVM). Declaring the variable as volatile
is the best way to avoid that optimization.
Upvotes: -3