Search code examples
javamultithreadingvolatile

When is non-volatile field write to main memory


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();
    }
}

Solution

  • 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.