Значения () потока ConcurrentHashMap безопасны? - PullRequest
1 голос
/ 04 мая 2019

Я новичок в Java8 и работаю над проблемой, когда несколько потоков (~ 10) записывают значения в Concurrent Hash Map. У меня есть другой специальный поток, который читает все значения, присутствующие в Concurrent Hash Map, и возвращает их (каждые 30 секунд). Является ли метод итерации по результату метода values ​​() рекомендуемым способом получения результатов без получения исключения одновременной модификации?

Примечание: я прекрасно справляюсь с получением устаревших данных

Я просмотрел официальные документы, в которых написано:

Операции получения обычно не блокируются, поэтому могут перекрываться с операциями обновления. Извлечения отражают результаты самых последних завершенных операций обновления, проводимых с момента их появления. Для агрегатных операций, таких как putAll и clear, одновременный поиск может отражать вставку или удаление только некоторых записей. Аналогично, Итераторы, Сплитераторы и Перечисления возвращают элементы, отражающие состояние хеш-таблицы в некоторой точке во время или после создания итератора / перечисления. Они не генерируют исключение ConcurrentModificationException.

Однако метод doc values ​​() говорит:

Возвращает представление коллекции значений, содержащихся в этой карте

Безопасен ли приведенный ниже кодовый поток?

for (String name: myMap.values()) {
     System.out.println("name": + name);
}

1 Ответ

2 голосов
/ 04 мая 2019

Является ли итерация по результату метода values() рекомендуемым способом получения результатов без получения ConcurrentModificationException?

Да. Это рекомендуемый способ, и вы не получите ConcurrentModificationException.

В качестве javadoc уровня пакета говорится:

Большинство одновременных реализаций Collection (включая большинство очередей) также отличаются от обычных соглашений java.util тем, что их итераторы и сплитераторы обеспечивают слабосогласованный, а не быстрый обход:

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

Безопасен ли приведенный ниже кодовый поток?

  for (String name: myMap.values()) {
       System.out.println("name": + name); 
  }

Да ... с некоторыми уточнениями.

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

Мы можем сказать следующее:

  1. Итерация увидит значения в соответствии с ранее заявленными гарантиями.
  2. Модель памяти гарантирует, что не должно быть никакого неприятного поведения со устаревшими значениями ... если только вы не мутируете объекты-значения после помещения их в карту. (Если вы это сделаете, то методы объекта должны быть реализованы, чтобы справиться с этим; например, они могут иметь значение synchronized. Это спорный вопрос для String значений, поскольку они неизменны.)
...