Ответ
Happens-before — это формальное отношение, определенное в Java Memory Model (JMM), которое гарантирует видимость и упорядоченность операций памяти между потоками. Если операция A happens-before операция B, то все изменения памяти, сделанные в A, будут видны потоку, выполняющему B.
Почему это важно: Без этих гарантий компилятор и процессор могут переупорядочивать инструкции для оптимизации, что в многопоточном коде может привести к неожиданным результатам (проблемы видимости и порядка).
Ключевые правила happens-before:
- Правило монитора (с synchronized / Lock): Разблокировка монитора happens-before последующая блокировка того же монитора.
- Правило volatile: Запись в volatile-поле happens-before каждое последующее чтение того же поля.
- Правило запуска потока: Вызов
thread.start()happens-before любое действие в запущенном потоке. - Правило завершения потока: Все действия в потоке happen-before вызов
thread.join()в другом потоке. - Правило транзитивности: Если A happens-before B, а B happens-before C, то A happens-before C.
Пример с volatile:
// Поток 1 (Писатель)
x = 42; // (1) Обычная запись
ready = true; // (2) Запись в volatile. (1) happens-before (2) (правило программы)
// Поток 2 (Читатель)
if (ready) { // (3) Чтение volatile. (2) happens-before (3) (правило volatile)
// Гарантированно увидит x = 42, потому что (1) happens-before (3) по транзитивности.
System.out.println(x); // (4)
}
Без модификатора volatile у переменной ready гарантии happens-before между потоками 1 и 2 нет, и поток 2 может увидеть ready == true, но при этом старое значение x = 0.