为什么写入非易失性对主线程可见?

Why is the write to non-volatile visible to the main-thread?

想象一下下面的程序。

class Main {


    static class Whatever {
        int x = 0;
    }


    public static void main(String[] args) {
        Whatever whatever = new Whatever();

        Thread t = new Thread(() -> {
            whatever.x = 1;
        });
        t.start();
        try {
            t.join();
        }
        catch (InterruptedException e) {
        }

        System.out.println(whatever.x);
    }
}

主线程已缓存 whatever 并且 x 设置为 0。另一个线程启动,缓存whatever并将缓存的x设置为1

输出为

1

所以主线程已经看到写入。这是为什么?

为什么对共享缓存进行了写入,为什么主线程使其缓存无效以从共享缓存读取?为什么我这里不需要 volatile

因为主线程加入了它。看 JLS 中的 17.4.5:

All actions in a thread happen-before any other thread successfully returns from a join() on that thread.

顺便说一句,确实没有 happens-before 并不一定意味着某些东西不可见。