ConcurrentHashMap 解决高并发下线程安全与性能平衡问题:避免 HashMap 死循环、取代 Hashtable 全局锁、支持无锁读与细粒度写、提供弱一致性遍历及红黑树优化。

ConcurrentHashMap 解决的核心问题是:在高并发场景下,既要保证线程安全,又不能牺牲读写性能。它直击两个典型痛点——HashMap 的线程不安全(多线程 put 可能引发死循环、数据丢失),以及 Hashtable 或 Collections.synchronizedMap 的粗粒度锁(整个表一把锁,导致大量线程串行等待)。
避免 HashMap 的并发死循环与数据错乱
HashMap 在 JDK7 及之前采用头插法扩容,多线程同时触发 resize 时,可能因链表节点重排顺序不当,形成环形链表。后续 get 操作陷入无限遍历,CPU 占用飙高至 100%。ConcurrentHashMap 从设计上杜绝这种风险:它不共享同一链表结构做无保护修改,所有结构性变更都受控于锁或 CAS,确保链表始终为有向无环结构。
取代 Hashtable 的全局锁瓶颈
Hashtable 对每个 public 方法加 synchronized,等效于锁住整个对象实例。这意味着即使线程 A 在 put("user1", …),线程 B 调用 get("config") 也必须阻塞等待——读写完全互斥,吞吐量随线程数增长几乎不升反降。
- ConcurrentHashMap 让读操作基本无锁:get、containsKey 等通过 volatile 读 + 链表遍历完成,无需同步
- 写操作锁粒度极细:JDK7 锁 Segment(默认 16 段),JDK8 进一步细化到单个桶的首节点(synchronized on Node)
- 允许多个线程同时读、多个线程在不同桶中写,真正实现“读读并发、读写并发、写写隔离”
支持高并发下的可靠统计与遍历
传统同步容器在 size() 或迭代时需锁全表,易成性能热点。ConcurrentHashMap 提供更实用的替代方案:
立即学习“Java免费学习笔记(深入)”;
- size() 和 mappingCount() 不依赖全局锁:通过 CAS 累加每个桶的修改计数,结果是近似值但响应极快
- 迭代器采用弱一致性(weakly consistent):不抛 ConcurrentModificationException,可安全遍历过程中被其他线程修改的 Map,看到的是某一时点的快照,兼顾安全性与可用性
适应动态负载的数据结构演进
面对海量键值对和长链表查询慢的问题,ConcurrentHashMap 在 JDK8 引入自适应优化:
- 当单个桶中链表长度 ≥ 8 且 table.length ≥ 64 时,自动转为红黑树,查找时间从 O(n) 降至 O(log n)
- 树化与退化逻辑由 CAS 和 synchronized 协同控制,全程线程安全
- 扩容过程分段进行,新老 table 并存过渡,避免 STW(Stop-The-World)式卡顿










