Есть ли недостатки у ConcurrentHashMap?

Мне нужен HashMap, доступный из нескольких потоков.

Есть два простых варианта: использование обычного HashMap и синхронизация на нем или использование ConcurrentHashMap.

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

Карта также будет очень маленькой (менее десяти записей), если это имеет значение.

По сравнению с обычным HashMap, насколько дороже операции чтения и записи (я предполагаю, что они есть)? Или ConcurrentHashMap всегда лучше, когда может быть даже умеренный уровень одновременного доступа, независимо от соотношения чтения/обновления и размера?


person Thilo    schedule 17.10.2010    source источник
comment
Точный дубликат вопроса? stackoverflow.com/questions/1378310/   -  person andersoj    schedule 17.10.2010
comment
Конечно. Спасибо. (Однако пока нет удовлетворительного ответа)   -  person Thilo    schedule 17.10.2010


Ответы (4)


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

Стоимость приобретения и освобождения неконкурентного мьютекса Java (примитивная блокировка) ничтожно мала. Так что, если вы считаете, что вероятность разногласий очень мала, то, вероятно, лучше всего подойдет простая HashMap.

Но это все домыслы. Если и до тех пор, пока вы фактически не профилируете свое приложение, все время, потраченное на спекулятивную оптимизацию, скорее всего (*) потрачено впустую.

* ... если у вас действительно хорошая интуиция.

person Stephen C    schedule 17.10.2010
comment
Стивен С прав (его представитель предполагает, что это привычка). В общем случае неоспариваемые блокировки выполняются быстро... Возможно, я слишком быстро добираюсь до CHM. - person andersoj; 17.10.2010
comment
А как насчет масштабирования? То, что ожидается, и то, что может случиться, совершенно разные. Если блокировки/разблокировки так мало, просто используйте ConcurrentHashMap и двигайтесь дальше - person TheLQ; 17.10.2010
comment
@TheLQ - это другие накладные расходы (помимо блокировки) использования ConcurrentHashMap, которые вызывают беспокойство. Вы не просто бросаете CCM на проблему, предполагая, что масштабируемость будет проблемой. Вы сначала измерьте! - person Stephen C; 17.10.2010
comment
Вы не просто бросаете CCM на проблему, предполагая, что масштабируемость будет проблемой. Именно этого ответа я и ждал. Теперь все, что мне нужно, — это несколько рекомендаций о том, когда CHM будет оправдан (потому что не каждый может каждый раз профилировать свое приложение). - person Thilo; 17.10.2010
comment
Если вы не управляете тысячами ComcurrentHashMaps, накладные расходы настолько малы, что вы никогда их не заметите. Я придерживаюсь этого принципа: если к нему будут обращаться и изменять несколько потоков, используйте ConcurrentHashMap. Это не дает мне тратить часы на проблемы с потоками, которые появляются только иногда при определенных небольших условиях, вещи, которые не всегда отображаются в вашем профиле. @Thilo, этот принцип сработает - person TheLQ; 17.10.2010
comment
@TheLQ - А. Ваши проблемы с потоками, которые появляются только иногда, комментируют, подразумевая, что реальная проблема, которую вы пытаетесь решить с помощью CCM, - это карты, которые не синхронизируются должным образом. (И то, что вы отстаиваете, эквивалентно замене всех ArrayList на Vectors или всех StringBuilders на StringBuffers.) Вопрос Thilo касается CCM и правильно синхронизированного HashMap. - person Stephen C; 22.02.2013

CHM платит некоторый штраф за использование операций Atomic* под прикрытием по сравнению с HashMap. Сколько? Угадайте, что... измерьте это в своем приложении... ;-)

Если вы обнаружите, что у вас действительно есть проблема с производительностью, вероятно, есть очень специализированное решение для ‹10 записей, которое будет дешевле, чем любое решение, собранное из java.util земли, но я бы не стал переходить к нему, пока вы не узнаете, что у вас есть проблема с производительностью. .

person andersoj    schedule 17.10.2010
comment
Вопрос, который у меня есть, заключается в том, должен ли я перейти к использованию ConcurrentHashMap, прежде чем я узнаю, что у меня проблема с производительностью. Я бы не хотел этого делать, если бы CHM был на самом деле медленнее, чем HashMap, в случае отсутствия параллелизма. - person Thilo; 17.10.2010
comment
Думаю, я бы использовал CHM, если сразу становится очевидным, что вы можете получить желаемый контроль параллелизма с putIfAbsent() и т.п.; Я бы использовал synchronized(normalHashMap), если вы заранее знаете, что операция put() будет сложной. (Оптимизация любого из них позже, если это проблема...) - person andersoj; 17.10.2010

С точки зрения пропускной способности и производительности накладные расходы обычно незначительны.

С другой стороны, объем памяти ConcurrentHashMap (на уровне экземпляра) несколько больше, чем у HashMap. Если у вас есть большое количество CHM небольшого размера, эти накладные расходы могут возрасти.

person sjlee    schedule 17.10.2010

Основная проблема с CHM: он плохо масштабируется, если вы не измените вызов c-tor, но в основном он не масштабируется автоматически для доступных ядер.

3 ссылки ниже на хэш-карту без блокировки
http://www.azulsystems.com/blog/cliff-click/2007-03-26-non-blocking-hashtable
http://www.azulsystems.com/blog/cliff-click/2007-04-01-non-blocking-hashtable-part-2
http://sourceforge.net/projects/high-scale-lib/

person bestsss    schedule 24.01.2011