Какой ключевой принцип определяет модель памяти Java (Java Memory Model, JMM)?

«Какой ключевой принцип определяет модель памяти Java (Java Memory Model, JMM)?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевой принцип Java Memory Model — Happens-Before. Он определяет гарантии порядка выполнения операций между потоками, обеспечивая видимость изменений памяти.

Суть принципа: Если операция A happens-before операция B, то все изменения памяти, сделанные в A, будут видны потоку, выполняющему B.

Пример гарантии happens-before:

// Общие переменные
int value = 0;
boolean flag = false;

// Поток 1 (Писатель)
value = 42;          // Операция (1)
flag = true;         // Операция (2) - запись в volatile

// Поток 2 (Читатель)
if (flag) {          // Операция (3) - чтение volatile
    // Гарантированно увидит value = 42, потому что (1) happens-before (2),
    // а (2) happens-before (3) по правилу volatile.
    System.out.println(value); // Выведет 42
}

Основные правила happens-before в JMM:

  1. Монитор (synchronized): Выход из блока happens-before последующий вход в тот же монитор.
  2. Volatile переменные: Запись в volatile happens-before последующее чтение той же переменной.
  3. Запуск потока: Вызов thread.start() happens-before первое действие в запущенном потоке.
  4. Завершение потока: Все действия в потоке happen-before другой поток успешно завершил thread.join().

Эти правила позволяют писать корректные многопоточные программы без полагания на конкретную реализацию JVM или процессора.