Будет ли синхронизация Java обновлять весь кэш или только объект, на котором я синхронизировался? - PullRequest
10 голосов
/ 28 августа 2011

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

Представьте, что есть объект Queue, имеющий синхронизированный метод add() и take(), принимающий и раздающий сложный объект Thing.Thing имеет много списков с другими объектами.

Теперь поток изображения Before создает Thing и помещает некоторые существующие объекты в Thing, модифицирует некоторые из этих объектов и так далее.Поток Before добавляет Thing к Queue.Чуть позже поток After берет Thing из Queue.

ВОПРОС: Будет ли Thing и все его дочерние / субобъекты находиться в том же состоянии, в котором Before оставил их?Даже если поток After работал над одним из этих подэлементов немного раньше?Поскольку я представляю, что процессор для потока After может все еще иметь некоторую кэшированную информацию об этом подэлементе (адрес этого подобъекта остается прежним).Все эти кэшированные данные будут признаны недействительными только через синхронизированный доступ к отцовскому объекту Thing?

Пожалуйста, не давайте ответов, таких как использование библиотек параллелизма и т.д.1028 *

Ответы [ 2 ]

9 голосов
/ 28 августа 2011

Если поток изменяет переменную, другой поток не может видеть изменения, за исключением следующих случаев (ну, по крайней мере, в следующих случаях; я не уверен на 100%, если их больше):

  • модифицирующий поток покидает синхронизированный блок или метод;это вызывает очистку кэша потока (аналогично потоку, который входит в синхронизированный блок, или метод вызывает обновление) - это то, что происходит в вашем случае
  • измененная переменная объявляется volatile или это однаиз атомарных переменных из java.util.concurrent.atomic
  • завершающий модифицирующий поток (это также вызывает сброс, аналогично, начало потока вызывает обновление)

Так что, если вы синхронизируете какобъяснил, другие темы будут видеть все изменения.

7 голосов
/ 28 августа 2011

Важной концепцией в модели памяти Java является , предшествующее заказу . Результаты действий записи, которые произойдут до действия чтения, видны этим действиям чтения. Другие результаты могут быть или не быть видимыми.

Порядок случай-до вызывается порядком синхронизации действий между потоками и порядком действий natural в отдельных потоках.

Если вы в Before синхронизируете объект (например, Queue) и выполняете все свои манипуляции с Thing и его «подобъектами» внутри или перед этим синхронизированным блоком, а After синхронизируется с тот же Queue и читает эти объекты в или после синхронизированного блока, затем все эти изменения видны для After.

...