Безопасная публикация без происшествий? Во всяком случае, кроме финала? - PullRequest
6 голосов
/ 28 марта 2011

Согласно JCP (16.2.2. Безопасная публикация):

Эта гарантия до того, как это произойдет, на самом деле более надежное обещание наглядности и порядка, чем безопасная публикация .Когда X безопасно публикуется из A в B, безопасная публикация гарантирует видимость состояния X, но не состояния других переменных, которые могли коснуться.Но если A помещает X в очередь - до того, как B извлекает X из этой очереди, B не только видит X в состоянии, в котором A его покинул (при условии, что X не был впоследствии изменен A или кем-либо еще), но B видитвсе, что А делал перед передачей (опять же, с учетом того же предостережения)

Мне интересно, когда безопасная публикация может быть без события до того, т.е. без использования volatile / atomics или синхронизации (иличерез фреймворки, такие как AQS, которые используют любой из перечисленных внутри)?

Один случай - это заключительные поля в неизменяемом объекте, где вы можете опубликовать его без каких-либо дополнительных шагов.

Есть лилюбые другие случаи?

UPD: перечитайте 3.5.3.Safe Publication Idioms, другой случай - «Инициализация ссылки на объект из статического инициализатора».Кажется, теперь это все варианты.

Ответы [ 3 ]

2 голосов
/ 28 марта 2011

Весь список случаев, которые вы можете найти в Java In Concurrency:

Для безопасной публикации объекта и ссылка на объект, и состояние объекта должны быть видимыми для других потоков одновременно.время.Правильно сконструированный объект может быть безопасно опубликован:

Инициализация ссылки на объект из статического инициализатора;

Сохранение ссылки на него в энергозависимом поле или AtomicReference;

Хранениессылка на него в конечном поле правильно построенного объекта;или

Сохранение ссылки на него в поле, которое должным образом защищено замком.

2 голосов
/ 28 марта 2011

Я ничего не знаю, кроме final, и взгляд на http://java.sun.com/docs/books/jls/third_edition/html/memory.html, кажется, подтверждает это.Глава 17.4 рассматривает все, кроме final, что объясняется отдельно в 17.5.

Следует отметить, однако, что все, что является внутренним для JVM, всегда должно быть сделано видимым, прежде чем оно может внести свой вклад в гонку данных.в коде Java.Это затрагивает в основном длины массивов, указатели виртуальных таблиц и содержимое строк.Они никогда не могут рассматриваться как неинициализированные или иным образом несовместимые.

1 голос
/ 28 марта 2011

статическая инициализация выполняется внутри synchronized(class), поэтому она очень сильная.

в то время как семантика final слабее, я сомневаюсь, что реализация действительно настолько слабая.

У Дуга Ли было предложение о более примитивных заборах, http://cs.oswego.edu/pipermail/concurrency-interest/2009-January/005743.html

...