Почему вызов конструктора объекта гарантирует отношение happens-before в Java Memory Model?

«Почему вызов конструктора объекта гарантирует отношение happens-before в Java Memory Model?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Согласно Java Memory Model (JMM), вызов конструктора объекта и его завершение happens-before (происходит-до) любого последующего действия, которое начинает использовать этот полностью проинициализированный объекмент.

Почему это важно для потокобезопасности:

  1. Запрет переупорядочивания: JVM и процессор не могут вынести запись полей из конструктора за его пределы и сделать их видимыми другим потокам до завершения конструктора.
  2. Безопасная публикация (Safe Publication): Если ссылка на объект становится видна другому потоку после полного завершения его конструктора, то этот поток гарантированно увидит все final-поля инициализированными так, как это задано в конструкторе. Для не-final полей также гарантируется корректная видимость при правильной публикации (например, через volatile-ссылку).

Пример проблемы и гарантии:

public class UnsafePublication {
    private int value;
    public UnsafePublication(int v) { this.value = v; }
}
// Поток 1: Создание и публикация (НЕПРАВИЛЬНО)
UnsafePublication ref = new UnsafePublication(42);
sharedRef = ref; // Публикация ссылки без синхронизации
// Поток 2 может увидеть `sharedRef` != null, но `value` == 0 (значение по умолчанию)

public class SafePublication {
    private final int value; // final поле
    public SafePublication(int v) { this.value = v; }
}
// Поток 1:
SafePublication ref = new SafePublication(42); // Завершение конструктора happens-before...
sharedRef = ref; // ...публикации ссылки (если sharedRef — volatile/final/публикуется через synchronized)
// Поток 2, увидев sharedRef, гарантированно увидит value = 42.

Ключевой вывод: Конструктор создает точку happens-before, которая обеспечивает корректную видимость инициализированного состояния объекта для других потоков при безопасной публикации.