Я читаю «Многопроцессорные вычисления» Нира Шавита. Это объясняет Java модель памяти и дает пример на странице 62:Слабость для Singleton в модели памяти Java с синхронизированными блоками
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
и говорит, что:
Эта модель, как только общее, является неправильным. На строке 5 вызов конструктора появляется, прежде чем поле экземпляра будет назначено, но модель памяти Java позволяет этим шагам возникнуть не в порядке, эффективно делает частично инициализированный Singleton-объект видимым для других программ.
Итак, означает ли это, что такая синхронизация может не гарантировать того, что мы хотим от Singleton?
Однако книга также говорит, что: «Хотя чтение и запись изменчивого поля оказывает такое же влияние на память, как получение и освобождение блокировки, множественные чтения-записи не являются атомарными. Например, если x является изменчивой переменной, выражение x ++ не обязательно будет увеличивать x, если одновременные потоки могут изменять x. Необходима также форма исключения . Один общий шаблон использования для изменчивых переменных возникает, когда поле считывается несколькими потоками, но записывается только одним. ' – kamaci
@RealSkeptic, поскольку Sotirios Delimanolis отредактировал его ответ. Я хочу стабильный объект (это может не нарушать одноконтактный контракт как термин) , Sotirios Delimanolis, вы уверены, что это может быть исправлено с изменчивым из-за моего первого комментария в вашем ответе. – kamaci
@kamaci Да, поэтому 'x ++' - две операции, это чтение 'x' и запись' x'. Это означает, что 'x ++' как операция не является атомарной. Если какой-либо другой поток записывается в 'x' до того, как' ++ 'может быть написан, вы потеряете эту запись. В этом случае мы предполагаем, что единственным «потоком», который может писать «экземпляр», является тот, который ввел «синхронизированный» блок. –