Java произошла раньше в синхронизированном блоке - PullRequest
3 голосов
/ 26 ноября 2011

Мне нужна помощь в понимании модели памяти Java. Ниже приведен пример для понимания базовой концепции:

Изображение У меня есть экземпляр объекта с именем Shared и два потока A и B.Кроме того, есть некоторый тип Queue с синхронизированными put и take.

Thread A, изменяющий Shared -экземпляр перед и in метод put.

Вопрос 1: Все изменения с A видны, когда B получает экземпляр Shared -объекта через синхронизированный take -метод?

Вопрос 2: Кэш памяти очищается (все изменения на Shared видны), как только A покидает синхронизированный put -метод.Что произойдет, если wait() вызывается в put -методе A?B также увидит изменения, внесенные в Shared, даже если A еще не вышел из synchronized -метода?Кэш также очищается при вызове wait()?

Ответы [ 3 ]

4 голосов
/ 26 ноября 2011

Ответ 1 : Да. Потому что take () и put () синхронизированы. Поэтому, прежде чем B сможет выполнить take (), A должен был покинуть синхронизированный блок, и выход из синхронизированного блока означает очистку кеша памяти (забор / барьер памяти).

Ответ 2 : Да. Потому что, когда вызывается wait (), поток должен снять блокировку, что снова вызовет сброс памяти.

РЕДАКТИРОВАТЬ: Я думаю, что вы после того, что запись в кэш-память происходит при выходе из синхронизированного блока или снятия блокировки. Ответ: запись в кэш-память происходит при снятии блокировки .

2 голосов
/ 26 ноября 2011

А еще не вышли из синхронизированного метода?Кэш также очищается при вызове wait ()?

Цитирование из JSR 133 (модель памяти Java) FAQ - Что делает синхронизация? :

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

Это говорит о том, что сброс кеша в память происходит при освобождении монитора.Обратите внимание, что хотя монитор освобождается при выходе из синхронизированного блока, он также освобождается при вызове метода ожидания.Поэтому я ожидаю, что изменения будут сброшены при вызове #wait () и будут приняты другим потоком, если он ожидал ранее на том же мониторе.

2 голосов
/ 26 ноября 2011

Ответом на ваши первые вопросы является «Да», поскольку точки синхронизации (присутствующие в «положи и забери») вводят неявные ограждения памяти.

Для второго вопроса это зависит от того, ожидают ли вызовы А до или после объекта.добавлено к Shared.Если это раньше, то очевидно, что нет изменений в общем доступе, и поэтому в B нет ничего нового, чтобы увидеть.

Редактировать : Если вызовы A ожидают позже, то изменение видно, потому что вы имелиполучить блокировку перед добавлением, а затем отпустить ее при ожидании, что также вводит забор.

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

...