Lesson 12 / 38

The Java Memory Model

Learn the happens-before relation — the only guarantee that one thread sees another's writes — and why unsynchronized code can be reordered by the compiler and CPU.

happens-before

The JMM only guarantees one thread sees another's write if a happens-before edge links them: unlocking then locking the same monitor, writing then reading the same volatile, Thread.start(), Thread.join(), and constructor-to-final-field reads. Without such an edge, the compiler and CPU may reorder freely.

Broken double-checked locking

Without volatile, a reader thread can observe a partially-constructed instance because the JMM allows the constructor write and the field write to be reordered. volatile adds the happens-before edge that fixes it.

class Config {
    private static volatile Config instance;   // volatile is required
    static Config get() {
        if (instance == null) {
            synchronized (Config.class) {
                if (instance == null) instance = new Config();
            }
        }
        return instance;
    }
}