Следует ли выполнять синхронизацию, чтобы избежать проблем с видимостью при использовании классов java.util.concurrent? - PullRequest
5 голосов
/ 28 октября 2010

При использовании любого из классов java.util.concurrent, мне все равно нужно синхронизировать доступ к экземпляру, чтобы избежать проблем с видимостью между разными потоками?* При использовании экземпляра java.util.concurrent возможно ли, чтобы один поток изменил экземпляр (т. Е. Поместил элемент в параллельную хэш-карту), и последующий поток не увидел изменение?

Мой вопрос возникает из-за того, что модель памяти Java позволяет потокам кэшировать значения, а не извлекать их непосредственно из памяти, если доступ к значению не синхронизирован.

Ответы [ 2 ]

3 голосов
/ 28 октября 2010

В пакете java.util.concurrent Свойства согласованности памяти вы можете проверить API Javadoc для пакета:

Методы всех классов в java.util.concurrent и его подпакеты расширяют эти гарантии для синхронизации более высокого уровня.В частности:

  • Действия в потоке перед помещением объекта в любую одновременную коллекцию случайные действия до действия после доступа или удаления этого элемента из коллекции в другом потоке.
    [...]
  • Выполняются действия перед «выпуском» методов синхронизатора, таких как
    Lock.unlock, Semaphore.release и
    CountDownLatch.countDown
    -перед действиями после успешного метода «получения», такого как Lock.lock, Semaphore.acquire, Condition.await и CountDownLatch.await над тем же объектом синхронизатора в другом потоке.
    [...]

Итак, классы в этом пакете проверяют параллелизм, используя набор классов для управления потоками (Lock, Semaphore и т. Д.).Эти классы обрабатывают логику случай-до программно, то есть управляют стеком FIFO параллельных потоков, блокируют и освобождают текущие и последующие потоки (то есть, используя Thread.wait() и Thread.resume() и т. Д.

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

0 голосов
/ 28 октября 2010

Поскольку ConcurrentHashMap (например) предназначен для использования из параллельного контекста, вам не нужно синхронизировать его дальше. Фактически, это может подорвать оптимизацию, которую он вносит.

Например, Collections.synchronizedMap (...) представляет собой способ сделать поток карты безопасным, насколько я понимаю, он работает по сути, заключая все вызовы в ключевое слово synchronized. Что-то вроде ConcurrentHashMap, с другой стороны, создает синхронизированные «сегменты» между элементами в коллекции, вызывая более тонкий контроль параллелизма и, следовательно, снижая конкуренцию за блокировку при интенсивном использовании. Это может также не заблокировать чтение, например. Если вы снова обернетесь этим с каким-то синхронизированным доступом, вы можете это подорвать. Очевидно, вы должны быть осторожны, чтобы синхронизировать весь доступ к коллекции и т. Д., Что является еще одним преимуществом более новой библиотеки; вам не нужно беспокоиться (как много!).

Коллекции java.lang.concurrent могут реализовать безопасность своих потоков с помощью syncrhonised. в этом случае спецификация языка гарантирует видимость. Они могут реализовать вещи без использования замков. Я не настолько ясен в этом, но я предполагаю, что такая же видимость была бы здесь.

Если вы видите, как выглядит потерянное обновление в вашем коде, возможно, это просто состояние гонки. Что-то вроде ConcurrentHashpMap даст вам самое последнее значение для чтения, и запись, возможно, еще не была записана. Часто это компромисс между точностью и производительностью.

Дело в том; java.util.concurrent материал предназначен для этой цели, поэтому я уверен, что он обеспечивает видимость и использование энергозависимой и / или дополнительной синхронизации не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...