Код, который ты показал, не потокобезопасен, несмотря на использование паттерна двойной проверки. Хотя на вид он предотвращает множественное создание объектов, есть критическая проблема с видимостью.
Основная уязвимость связана с переупорядочиванием инструкций JIT-компилятором. При создании объекта компилятор может присвоить ссылку instance до завершения конструктора. Это означает, что другой поток может получить частично инициализированный объект.
Вот проблемная последовательность:
1. Память выделена для instance
2. Ссылка присвоена (видна другим потокам)
3. Конструктор выполняется (объект ещё не готов)
Добавь ключевое слово volatile к переменной instance:
private volatile SingletonDoubleCheck instance = null;
Ключевое слово volatile гарантирует:
instancepublic class SingletonDoubleCheck {
private volatile SingletonDoubleCheck instance = null;
public SingletonDoubleCheck getInstance() {
if (instance == null) {
synchronized (SingletonDoubleCheck.class) {
if (instance == null) {
instance = new SingletonDoubleCheck();
}
}
}
return instance;
}
}
Паттерн двойной проверки требует volatile для потокобезопасности. Без него рискуешь получить частично инициализированные объекты. Это тонкая, но критическая проблема многопоточности в Java.
Ключевое слово volatile предотвращает переупорядочение присваивания ссылки JIT-компилятором до завершения конструктора, обеспечивая видимость памяти между потоками.
Новый — ещё не проверен сообществом
Вы