Синхронизированные блоки необходимы для очередей блокировки - PullRequest
2 голосов
/ 24 марта 2019
public BlockingQueue<Message> Queue;
Queue = new LinkedBlockingQueue<>();

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

Это то же самое для очередей блокировки?

Ответы [ 3 ]

2 голосов
/ 24 марта 2019

Нет, вам не нужно окружать синхронизированными блоками.

Из JDK javadocs ...

Реализации BlockingQueue являются поточно-ориентированными.Все методы очередей достигают своих эффектов атомарно, используя внутренние блокировки или другие формы управления параллелизмом.Однако массовые операции Collection addAll, containsAll, retainAll и removeAll не обязательно выполняются атомарно, если в реализации не указано иное.Так что, например, addAll (c) может потерпеть неудачу (вызывая исключение) после добавления только некоторых элементов в c.

Просто хочу указать, что из моего опыта классыв пакете java.util.concurrent JDK блоки синхронизации не нужны.Эти классы управляют параллелизмом для вас и обычно являются поточно-ориентированными.Намеренно или нет, похоже, что java.util.concurrent заменил необходимость использовать блоки синхронизации в современном коде Java.

1 голос
/ 24 марта 2019

Вы думаете о синхронизации на слишком низком уровне. Это не имеет никакого отношения к тому, какие классы вы используете. Речь идет о защите данных и объектов, которые совместно используются потоками.

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

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


Java Collections.synchronizedList(...) дает возможность двум или более потокам совместно использовать List таким образом, чтобы сам список был защищен от повреждения действием различных потоков. Но он не предлагает никакой защиты для объектов данных, которые в List. Если ваше приложение нуждается в такой защите, то вы должны предоставить ее.

Если вам нужна эквивалентная защита для очереди, вы можете использовать любой из нескольких классов, реализующих java.util.concurrent.BlockingQueue. Но будьте осторожны! То же самое относится Сама очередь будет защищена от повреждения, но защита не распространяется автоматически на объекты, которые ваши потоки проходят через очередь.

1 голос
/ 24 марта 2019

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

  1. Случай 1: Не требуется при использовании методов организации очереди, например положить, взять и т. д.

    Почему не требуется объяснение здесь , важная строка ниже:

    Реализации BlockingQueue являются поточно-ориентированными. Все методы очередей добиться их эффекта атомарно, используя внутренние замки или другие формы управления параллелизмом.

  2. Случай 2: Требуется при переборе очередей блокировки и большинства одновременных коллекций

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

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