Java Memory Model

У каждого ядра процессора свой кэш. Изменение переменной одним потоком может не дойти до другого потока сразу — он видит старое значение из своего кэша, а не из общей памяти.

CPU 1 Поток 1 L1/L2 кэш running = true ❌ CPU 2 Поток 2 L1/L2 кэш running = false ✓ Общая память (RAM) volatile / sync

Java Memory Model (JMM) — спецификация, которая описывает, при каких условиях изменения одного потока гарантированно видны другому. Без таких гарантий компилятор и процессор вольны переупорядочивать и кэшировать операции как удобно — это нормально для одного потока, но ломает многопоточный код.

Правило happens-before описывает эти гарантии: если операция A happens-before B, то все изменения A гарантированно видны B.

// Без volatile — поток 1 может вечно видеть true из своего кэша
volatile boolean running = true;
// volatile гарантирует: запись в running сразу идёт в общую память,
// а чтение — всегда из общей памяти (не из кэша ядра).
Копнуть глубже

Правила happens-before в JMM. JMM гарантирует видимость в следующих случаях:

СитуацияГарантия
volatile-запись → volatile-чтениеда
выход из synchronized → вход в тот же мониторда
Thread.start() → любой код в потокеда
завершение потока → Thread.join()да
порядок действий внутри одного потокавсегда

Reordering (переупорядочивание). Компилятор JIT и процессор могут менять порядок инструкций для оптимизации. JMM запрещает переупорядочивание только через happens-before барьеры. Пример проблемы — «двойная проверка» без volatile:

// НЕПРАВИЛЬНО — объект может быть виден как ненулевой до того,
// как конструктор завершился (переупорядочивание записи поля)
private static Singleton instance;

// ПРАВИЛЬНО
private static volatile Singleton instance;

public static Singleton getInstance() {
    if (instance == null) {
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton(); // volatile → барьер записи
            }
        }
    }
    return instance;
}
🎤 Закрыл тему, если можешь объяснить:
• зачем нужна Java Memory Model и что значит happens-before;
• почему volatile решает проблему видимости но не атомарности (если дошёл до 2-го слоя).