Публикация полей объектов, не относящихся к потокам, безопасным для потоков способом

У меня проблема с Java Concurrency. Да, я смотрел на вопросы с почти одинаковым названием, но все они, казалось, задавали несколько разные вещи. Да, я прочитал Java Concurrency in Practice . Да, я понимаю, почему это ссылка defacto для этой темы. Да, я прочитал раздел специально о публикации полей в потокобезопасных классах. Да, я все еще собираюсь задать вопрос о параллелизме в Java, несмотря на то, что я знаю, что кто-то просто укажет мне на эту книгу.

Это меня озадачило - я знаю, что вы можете легко публиковать изменяемые примитивные поля потокобезопасным способом, обеспечивая правильные порядки чтения / записи с изменчивостью и / или синхронизированным доступом, и что 64-битные примитивы должны иметь атомарный доступ из-за отсутствия атомарности в его операциях чтения / записи. Я знаю об использовании блокировок кусков кода, которые необходимо выполнить на определенном «снимке» полей класса. Я полностью осведомлен об атомарном пакете с такими вещами, как AtomicLong <> и т. Д.

Но я все еще не понимаю, как публиковать небезопасные для потоков объекты как поля в потокобезопасном классе.

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

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

Я имею в виду, что если вы вернете AtomicReference <> объекту в геттере, они могут просто использовать .get (), чтобы снова получить несинхронизированный доступ к нему.

Еще один способ, который я рассмотрел, заключался в том, чтобы все геттеры возвращали новые копии объекта, не являющегося потокобезопасным, на основе старого, а это означало, что модификации не будут иметь значения, с тем же самым применением к сеттерам. Но у Java есть безнадежно сложная система для клонирования объектов (неглубокая копия против глубокой копии против специфического копирования и т. Д.), Что отчасти отталкивает меня от этого. Кроме того, это настолько неэффективно, что будет не быстрее, чем использование языка, предназначенного для неизменяемости, такого как Clojure. Фактически, это, вероятно, будет намного медленнее, учитывая, что такие языки позволяют нескольким частям неизменяемых данных совместно использовать одни и те же данные за кулисами.

Итак, как мне составить потокобезопасные классы опубликованных не-потокобезопасные объекты?

Заранее благодарим.

7
задан dsolimano 2 June 2012 в 04:34
поделиться