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

Я читаю книгу Java Concurrecny на практике. На странице 85 раздела 5.2.1 говорится о ConcurrentHashMap и его преимуществах. Однако в одной части книги утверждают, что

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

из того, почему я понимаю, что весь смысл синхронизации в параллельных программах заключается в том, чтобы разрешить потоку доступ к общему ресурсу согласованным образом, где ConcurrentHashMap на самом деле не выполняет это. Тогда зачем вообще его использовать?

3 ответов


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

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


ConcurrentHashMap должен быть потокобезопасным, по контракту. Однако, это не должно быть согласуются между потоками.

когда вы перебираете ConcurrentHashMap, итератор захватывает копию хэш-карты в тот момент, когда вы ее попросили (и этой копирование выполняется потокобезопасным способом), и вы повторяете эту копию. И да, ничто не гарантирует вам, что в то время как вы повторяете эту копию, некоторые записи карты не будут удалены. Но записи карты, которые будут удалены таким образом woud все еще существует в вашем итераторе.


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

однако иногда вам нужны гораздо более слабые требования, но, например, вы нужно скажите lock-free свойство, как вам нужно, чтобы гарантировать пропускную способность. С другой стороны, вам могут не понадобиться итераторы вообще или иметь гораздо более слабые ограничения на них.

Итак, если все, что вам нужно, это карта, общая для потоков ConcurrentHashMap (скажем, место в театре для бронирования) предоставит то, что вам нужно, - и это может быть намного быстрее, если у вас есть много рабочих потоков, поскольку вы избегаете синхронизации мьютексов. С другой стороны, скорость достигается ценой-представление, предоставляемое итератором, не обязательно соответствует состоянию коллекции при ее создании и может пропустить некоторые элементы, созданные после слов (в целом в многопроцессорных системах happens-before отношения-это сложно).

редактировать: Как Князь Джон Уэсли заметил, что я думал о ConcurrentSkipListMap во время просмотра и записи. ConcurrentHashMap. Большинство точек все еще стоят, за исключением частей о том, чтобы быть свободным от блокировки (а также все, что исходит из него, как гарантированная пропускная способность и т. д.).