В javadoc для ConcurrentHashMap есть следующее:
Операции извлечения (включая get) обычно не блокируются, поэтому могут перекрываться с операциями обновления (включая put и remove). Извлечения отражают результаты самых последних завершенных операций обновления, проводимых с момента их появления. Для агрегатных операций, таких как putAll и clear, одновременный поиск может отражать вставку или удаление только некоторых записей. Аналогично, Итераторы и Перечисления возвращают элементы, отражающие состояние хеш-таблицы в некоторой точке во время или после создания итератора / перечисления. Они не бросают ConcurrentModificationException. Однако итераторы предназначены для использования только одним потоком за раз.
Что это означает? Что произойдет, если я попытаюсь повторить карту с двумя потоками одновременно? Что произойдет, если я добавлю или уберу значение с карты во время итерации?
ConcurrentModificationException
итерацииConcurrentHashMap
, почему?Вы можете использовать этот класс, чтобы протестировать два потока доступа и один изменяющий общий экземпляр
ConcurrentHashMap
:Не будет исключений.
Совместное использование одного и того же итератора между потоками доступа может привести к тупику:
Как только вы начнете делиться тем же самым
Iterator<Map.Entry<String, String>>
между потоками доступа и мутатора,java.lang.IllegalStateException
s начнет появляться.источник
Это означает, что вы не должны делить объект итератора между несколькими потоками. Создание нескольких итераторов и одновременное их использование в отдельных потоках - это нормально.
источник
Это может дать вам хорошее понимание
В соответствии с этим:
Это означает, что использование безопасных итераторов, созданных ConcurrentHashMap в двух потоках, может привести к неожиданному результату в приложении.
источник
Это означает, что вы не должны пытаться использовать один и тот же итератор в двух потоках. Если у вас есть два потока, которым нужно перебирать ключи, значения или записи, то каждый из них должен создавать и использовать свои собственные итераторы.
Не совсем понятно, что произойдет, если вы нарушите это правило. Вы можете просто запутаться, точно так же, как если бы (например) два потока пытались читать со стандартного ввода без синхронизации. Вы также можете получить не поточнобезопасное поведение.
Но если два потока используют разные итераторы, у вас все будет хорошо.
Это отдельная проблема, но раздел javadoc, который вы цитировали, адекватно отвечает на него. По сути, итераторы являются поточно-ориентированными, но не определено , увидите ли вы результаты любых одновременных вставок, обновлений или удалений, отраженных в последовательности объектов, возвращаемых итератором. На практике это, вероятно, зависит от того, где на карте происходят обновления.
источник