Ответ
ConcurrentHashMap (CHM) обеспечивает высокую степень параллелизма за счет сегментирования блокировок (lock striping) и безблокировочных операций.
Основные механизмы (эволюция):
- До Java 8: Внутренняя таблица делилась на сегменты (Segment), каждый со своей блокировкой. Потоки, работающие с разными сегментами, не блокировали друг друга.
- Java 8+: Используется более оптимизированный подход:
- Блокировка на уровне узла (Node): Вместо сегментов блокируется только голова отдельного бакета (связного списка или дерева) при необходимости.
- CAS-операции (Compare-And-Swap): Для основных операций (например, вставка в пустой бакет) используются атомарные операции
sun.misc.Unsafe, что позволяет обойтись без блокировок. - Синхронизированные методы для отдельных операций: Критические секции минимальны и используют
synchronized.
Пример и преимущества:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// Потокобезопасные атомарные операции:
map.put("key", 1);
map.compute("key", (k, v) -> v + 1); // Атомарное обновление
Integer val = map.get("key"); // Чтение без блокировки
Ключевые отличия от Hashtable:
- Высокий параллелизм: Чтение почти никогда не блокируется, запись блокирует только отдельный бакет.
- Слабосогласованная итерация (weakly-consistent): Итератор отражает состояние мапы на момент его создания, но может не показывать последующие изменения.
- Отсутствие глобальной блокировки (lock-free для чтения).