0

Я читаю «Многопроцессорные вычисления» Нира Шавита. Это объясняет 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?

ответ

1

Итак, означает ли это, что такая синхронизация не может гарантировать то, что мы хотим от Singleton?

Это зависит от того, что вы хотите от синглтона. Если вам нужен только один экземпляр, решение в вашем фрагменте достигнет этого. Если вы хотите только один экземпляр и хотите, чтобы этот экземпляр был полностью инициализирован при доступе к нему (это слишком много, чтобы спросить?), Тогда нет, вы не достигнете этого с помощью фрагмента.

Другой поток вызова getInstance и чтение значение instance поля

if (instance == null) { 

может увидеть присвоенное значение, ссылающийся объект, который еще предстоит инициализируется контроллером. Поскольку это значение не равно null, метод возвращает его, а неинициализированный объект течет.

Исправлена, помеченная полем как volatile.

+0

Однако книга также говорит, что: «Хотя чтение и запись изменчивого поля оказывает такое же влияние на память, как получение и освобождение блокировки, множественные чтения-записи не являются атомарными. Например, если x является изменчивой переменной, выражение x ++ не обязательно будет увеличивать x, если одновременные потоки могут изменять x. Необходима также форма исключения . Один общий шаблон использования для изменчивых переменных возникает, когда поле считывается несколькими потоками, но записывается только одним. ' – kamaci

+0

@RealSkeptic, поскольку Sotirios Delimanolis отредактировал его ответ. Я хочу стабильный объект (это может не нарушать одноконтактный контракт как термин) , Sotirios Delimanolis, вы уверены, что это может быть исправлено с изменчивым из-за моего первого комментария в вашем ответе. – kamaci

+0

@kamaci Да, поэтому 'x ++' - две операции, это чтение 'x' и запись' x'. Это означает, что 'x ++' как операция не является атомарной. Если какой-либо другой поток записывается в 'x' до того, как' ++ 'может быть написан, вы потеряете эту запись. В этом случае мы предполагаем, что единственным «потоком», который может писать «экземпляр», является тот, который ввел «синхронизированный» блок. –