Reputation: 205
The following program hangs but if I uncomment the System.out.printf
it exits normally. I wonder why this happens. Thanks in advance.
public class MainClass{
public static class Node{
public Integer val;
Node() {
val = new Integer(0);
}
public void hang() {
int i = 0;
while(this.val != 1) {
// the program quit normally if I uncomment the following line
//System.out.printf("");
i++;
}
System.out.println(i);
System.out.println("quit");
}
private int func(int i) {
return i+1;
}
}
public static void main(String[] args) throws InterruptedException{
Node n = new Node();
Thread t = new Thread(new Runnable(){
@Override
public void run() {
n.hang();
}
});
t.start();
// wait for t to start
Thread.sleep(500);
n.val = new Integer(1);
Thread.sleep(500);
t.join();
}
}
output of java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.16.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
Upvotes: 2
Views: 209
Reputation: 549
The solution is shown in maslan's answer. However, as for your question, I think the reason why adding 'System.out.printf' will stop the hanging is that, if not, the JIT compiler will transform the code like:
if (this.val != 1) while(true) {i++;}
And I guess that adding the call will stop the JIT do that optimization. So when the thread decide to read from the memory and not using the cache, your program quited normally.
One proof for my guess is that by adding '-XX:LoopOptsCount=0' to the VM options, your original program (without the printf) quit normally.
Adding 'volatile' keyword to field declaration will also stop the transformation, see When Java refresh Thread Cache to actual copy
Upvotes: 1
Reputation: 2178
I believe that is because the values might be copied to CPU caches and that means that multiple threads might se a different values for the same variable. To prevent this you can tell java to use main memory. Please change "public Integer val" to "public volatile Integer val" and observe that the program now exits.
Se more on volatile here: When to use volatile with multi threading?
As you asked why does this happen: multithreading is a stuff that you should assume what happens is kinda random. My guess is that the thread at printf waits for some IO resource, and when waiting it is suspended, but when it resumes the cache is refreshed first. But as I just said, this is just a guess, as you are never sure when doing thread operations that are not synchronized
Upvotes: 5