concurrenthashmap 是大数据并发场景下替代 hashmap 和 hashtable 的硬性要求——hashmap 无同步保障易致死循环或数据丢失,hashtable 全表锁严重制约吞吐,而 concurrenthashmap 通过桶级锁、cas 无锁操作和渐进式扩容实现高效线程安全。

在大数据并发场景下,用 ConcurrentHashMap 替代 HashMap 或 Hashtable 不是权衡取舍,而是避免故障和性能崩塌的硬性要求——核心差距在于线程安全机制是否真实适配高并发现实。
HashMap 根本不能用于多线程写入
HashMap 没有任何同步保障。多个线程同时 put,尤其在触发扩容时,JDK 7 可能引发链表成环、get 死循环、CPU 100%;JDK 8 虽修复了环形链表,但依然存在:
- 数据覆盖:两个线程对同一 key 写入,一个值必然丢失
- 结构不一致:遍历时另一线程修改了 map,直接抛
ConcurrentModificationException - 读写混用无保障:哪怕“一读一写”,读线程也可能看到部分初始化、中间态甚至损坏的内部数组
Hashtable 锁太重,吞吐卡在单点
Hashtable 所有方法(get、put、size、containsKey)都用 synchronized 锁住整个对象:
- 哪怕线程 A 查
"user_1001",线程 B 存"order_9999",也必须排队等同一把锁 - 读操作被强制串行化,无法利用多核并行能力
- 扩容期间整个表不可用,请求延迟毛刺明显,不适合实时性要求高的服务
ConcurrentHashMap 的并发设计直击痛点
JDK 8+ 版本通过三重机制实现高效线程安全:
-
桶级细粒度锁:只对发生哈希冲突的单个桶(链表头或红黑树根)加
synchronized,不同桶完全并发 - CAS 无锁路径:空桶插入、计数更新、扩容协助等高频操作用 CPU 原子指令,避免锁开销
-
渐进式扩容:扩容不是一次搬完,而是在每次
put和get中分片搬运,新旧数组并存,全程不阻塞读写
它还额外提供 HashMap 和 Hashtable 都没有的能力
不只是“能并发”,更是“更聪明地并发”:
- 支持原子复合操作:
computeIfAbsent、merge、replace等,避免先查后写的竞态窗口 - 迭代器弱一致性:遍历时允许其他线程修改,不抛异常,也不要求锁表,适合监控、日志等容忍短暂延迟的场景
- size() 不再是全表扫描:通过 baseCount + 计数单元(CounterCell)分散更新,响应更快











