2009-07-01 3 views
1

Предполагая, что у меня есть следующий код:Threadsafe публикации структуры объектов java?

final Catalog catalog = createCatalog(); 

for (int i = 0; i< 100; i++{ 
    new Thread(new CatalogWorker(catalog)).start(); 
} 

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

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

ответ

5

Нет, нет Простой способ сделать это безопасным. Одновременное использование изменяемых типов данных всегда сложно. В ситуации ситуации, при которых каждая операция на Catalog синхронизирована (желательно на закрытом замке), может работать, но обычно вы обнаружите, что поток действительно хочет выполнить несколько операций, не рискуя любыми другими темами, ,

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

Любого неизменно состояния в Catalog должно быть хорошо уже: есть «происходит, прежде, чем» между строительством Catalog и новым потоком запуска. От section 17.4.5 из спецификации:

Вызов, чтобы начать() в потоке происходит, прежде чем любые действия в начал нить.

(И строительство отделка происходит перед вызовом start(), поэтому строительство происходит до каких-либо действий в запущенном потоке.)

+0

Хм, интересно: Вы говорите, что я в безопасности, если синхронизировать все обновления с изменяемым состоянием, даже если существует состояние, которое только «эффективно неизменено»? (Я * знаю * это рискованная модель с точки зрения обслуживания) – krosenvold

+0

Ну, я бы не сказал, что это делает вас безопасным в целом, но это делает вас безопасным в условиях чистой памяти. Обратите внимание, что вам нужно синхронизировать все * обращения *, а не только * обновления *, иначе вы могли бы получить «устаревшие» данные при его прочтении. –

+0

Yup. Хороший ответ;) – krosenvold

1

Вам необходимы синхронизировать каждый метод, который изменяет состояние Catalog, чтобы сделать его резьбовым безопасно.

public synchronized <return type> method(<parameter list>){ 
... 
} 
+0

Либеральная применение «синхронизируется» может привести к болезненным тупиков, если вы не осторожный. –

1

Предполагая, что вы справиться с «неконечными, нелетучими ссылками [и] изменяемое состояние» (предположительно, на самом деле не мутирует ничего, пока эти потоки работают), то я считаю, что это потокобезопасно. От the JSR-133 FAQ:

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

  • Каждое действие в потоке происходит перед каждым действием в этом потоке что приходит позже в порядке программы.
  • Разблокировка на мониторе происходит до каждой последующей блокировки на этом тот же монитор.
  • Запись в нестабильное поле происходит до каждого последующего чтения того же изменчивого.
  • Вызов для запуска() в потоке происходит до того, как какие-либо действия в начались.
  • Все действия в потоке происходят до того, как любой другой поток успешно завершится возвращает из join() в этом потоке.

Поскольку потоки запускаются после вызова createCatalog, результат createCatalog должен быть виден этими потоки без каких-либо проблем. Это только изменения объектов Catalog, которые возникают после вызова start() в потоке, который может вызвать проблемы.

+0

Хм, похоже, ваше первоначальное предположение действительно переопределяет мой вопрос, чтобы быть чем-то другим? Я * знаю * Мне нужно будет обрабатывать изменчивое состояние, но я надеялся, что есть способ избежать обработки всех неконкурентных, энергонезависимых вещей. – krosenvold

+0

Вы сказали: «Но это нужно будет обрабатывать», подразумевая, что вы знали, что эту часть нужно решать. Затем вы сказали: «Обобщенная версия этой проблемы действительно касается однопоточной конструкции общих структур, созданных до того, как потоки взорвутся в действие», на что я отвечаю: создание общих структур в одном потоке перед другими потоками, которые использовать их начали нормально. Если другие потоки были запущены до создания этих объектов, тогда возникла бы проблема, и для обеспечения согласованности вам понадобится еще один барьер памяти. –