Because the done
is non-volatile, so I will expect thread 1 will keep executing and printing out "Done".
But when I run the program, here is the output from console
Done
Undo
This means that thread 2's update is seen by thread 1, right? (But done
isn't a volatile field.).
My explanation is that thread 1 and thread 2 are running in the same core. So that they can see update of the filed, please correct me if I'm wrong.
Overall, my question is why thread 1 can see the change of thread 2? Is this related to CPU cache write back/through to main memory? If it is, when does it happen?
public class Done {
boolean done = true;
public void m1() throws InterruptedException {
while (this.done) {
System.out.println("Done");
}
System.out.println("Undo");
}
public void undo() {
done = false;
}
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
Done v = new Done();
es.submit(() -> {
try {
v.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}); // thread 1
es.submit(() -> {
v.undo();
}); // thread 2
es.shutdown();
}
}
The Java memory model's guarantees work in only one way. If something is guaranteed, like the visibility of a volatile write, then it'll work 100% of the time.
If there's no guarantee, it doesn't mean it'll never happen. Sometimes non-volatile writes will be seen by other threads. If you run this code many times on different machines with different JVMs, you'll probably see different results.