Параллелизм Java - почему синхронизация установщика (но не получателя) не делает класс потокобезопасным? [duplicate]

7
задан Community 23 May 2017 в 11:47
поделиться

4 ответа

В Java есть модель памяти «происходит до/после». Должна быть какая-то общая параллельная конструкция (например, синхронизированный блок/метод, блокировка, изменчивая, атомарная) как на пути записи, так и на пути чтения, чтобы вызвать такое поведение.

Если вы синхронизируете оба метода, вы создаете блокировку всего объекта, который будет совместно использоваться как потоками чтения, так и потоками записи. JVM гарантирует, что любые изменения, происходящие в потоке записи перед выходом из (синхронизированного) метода setInt, будут видны любым потокам чтения после того, как они войдут в (синхронизированный) метод getInt. JVM вставит необходимые барьеры памяти, чтобы гарантировать, что это произойдет.

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

Примечание. В частности, в этом случае создание изменчивого поля «число» даст правильное поведение, поскольку изменчивое чтение/запись также обеспечивает такое же поведение видимости памяти в JVM, а действие внутри метода setInt — это только присваивание.

6
ответ дан 6 December 2019 в 22:58
поделиться

Это объясняется в книге перед образцом (стр. 35):

"Синхронизация только сеттера была бы недостаточной: потоки, вызывающие get, все равно могли бы видеть устаревшие значения".

Устаревшие данные. Когда поток чтения проверяет готовность, он может обнаружить устаревшее значение. Если синхронизация не используется каждый раз при доступе к переменной, можно увидеть устаревшее значение для этой переменной. Хуже того, устаревание — это не принцип «все или ничего»: поток может видеть актуальное значение одной переменной, но устаревшее значение другой переменной, которая была записана первой.

5
ответ дан 6 December 2019 в 22:58
поделиться

Если вы только синхронизируете метод установки, вы можете только гарантировать, что атрибут не будет изменен неправильно, но вы не можете быть уверены, что это устаревшее значение, когда вы пытаетесь прочитать переменную.

1
ответ дан 6 December 2019 в 22:58
поделиться

поскольку число не является изменчивым и getInt() не синхронизировано, getInt() может возвращать устаревшие значения. Для получения дополнительной информации прочитайте о модели памяти Java.

-1
ответ дан 6 December 2019 в 22:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: