Проверяет instance == null один раз без блокировки (быстрый путь для всех вызовов после первого) и получает блокировку — со второй проверкой внутри — только при редком первом вызове. volatile требуется, поскольку new не является атомарным (выделить, построить, назначить); без него компилятор/JIT может изменить порядок присваивания до завершения конструктора, позволяя другому потоку увидеть ненулевую ссылку на частично инициализированный объект.
Пример
// Classic GoF Singleton: enforced by the class itselfpublicclassConfigManager {
privatestaticfinalConfigManagerINSTANCE=newConfigManager();
privateConfigManager() {} // private constructor blocks any other instantiationpublicstaticConfigManagergetInstance() { return INSTANCE; }
}
Итог
Проверяет instance == null один раз без блокировки (быстрый путь для всех вызовов после первого) и получает блокировку — со второй проверкой внутри — только при редком первом вызове.
Как блокировка с двойной проверкой делает Singleton потокобезопасны… · Sobeso