Skip to content

ConcurrentHashMap:高性能并发 Map

ConcurrentHashMap 是什么

ConcurrentHashMap 是 HashMap 的并发版本,提供高并发下的线程安全

java
// HashMap:非线程安全
Map<String, Integer> hash = new HashMap<>();

// ConcurrentHashMap:高并发线程安全
ConcurrentHashMap<String, Integer> chm = new ConcurrentHashMap<>();

vs HashMap / synchronizedMap

特性HashMapsynchronizedMapConcurrentHashMap
线程安全✅(全局锁)✅(分段锁/CAS)
并发读阻塞无锁读
性能最快较快
迭代安全Fail-Fast需额外同步Fail-Safe

JDK 8+ 的 CAS + synchronized

JDK 8 废弃了 JDK 7 的 Segment 分段锁,改为 CAS + synchronized

java
// 简单操作用 CAS(无锁操作)
U.compareAndSwapObject(table, ...);

// 需要锁定时用 synchronized(只锁单个桶)
synchronized (node) {
    // 对单个桶操作
}

每个桶一把锁,减少了锁竞争。


红黑树优化

当单个桶内链表过长时,转为红黑树:

java
// 链表长度 >= 8 且 数组容量 >= 64 → 转红黑树
// 和 HashMap 一样

核心 API

基本操作

java
ConcurrentHashMap<String, Integer> chm = new ConcurrentHashMap<>();

// put / get
chm.put("apple", 3);
chm.get("apple"); // 3

// putIfAbsent:不存在才插入
chm.putIfAbsent("apple", 10); // 返回 3(旧值),不覆盖
chm.putIfAbsent("banana", 5); // 返回 null,插入成功

原子操作

java
chm.put("count", 0);

// compute:重新计算值
chm.compute("count", (k, v) -> v == null ? 1 : v + 1);

// merge:合并
chm.merge("count", 1, Integer::sum);

// computeIfAbsent:不存在才计算
chm.computeIfAbsent("newKey", k -> calculateValue(k));

批量操作

java
// forEach:遍历(Fail-Safe,不会抛 ConcurrentModificationException)
chm.forEach((k, v) -> System.out.println(k + " = " + v));

// search:搜索
String found = chm.search(1, (k, v) -> v > 10 ? k : null);

// reduce:聚合
Long sum = chm.reduceValues(1, Long::sum);

与 synchronizedMap 的性能对比

java
// 10 个线程并发写入 10 万元素
// synchronizedMap:  ~8000 ms
// ConcurrentHashMap: ~200 ms
// 快了 40 倍!

迭代安全性

ConcurrentHashMap 的迭代器是 Fail-Safe 的,遍历的是快照副本:

java
ConcurrentHashMap<String, Integer> chm = new ConcurrentHashMap<>();
chm.put("a", 1);
chm.put("b", 2);

// 遍历过程中可以并发修改
for (Map.Entry<String, Integer> e : chm.entrySet()) {
    System.out.println(e.getKey() + " = " + e.getValue());
    chm.put("c", 3); // 不抛异常
}

synchronizedMap 做不到这一点。


注意事项

不允许 null

java
ConcurrentHashMap<String, Integer> chm = new ConcurrentHashMap<>();

// ❌ 不允许 null key 或 null value
chm.put(null, 1); // NullPointerException
chm.put("a", null); // NullPointerException

不适合做缓存

ConcurrentHashMap 不会自动清理:

java
// ❌ ConcurrentHashMap 不支持弱引用或自动过期
// 适合做计数器、共享状态等,不适合做大缓存

// ✅ 缓存用 Cache 或 WeakHashMap
LoadingCache<Key, Value> cache = Caffeine.newBuilder().build();

总结

要点说明
线程安全CAS + synchronized
性能比 synchronizedMap 快 10-40 倍
迭代安全Fail-Safe,遍历时无需额外同步
null不允许 null key/value
适用高并发 Map、计数器、共享状态

一句话:ConcurrentHashMap 是「高并发场景下的 HashMap」——用分段锁/CAS 替代全局锁,让多个线程并发读写而不阻塞。


相关链接

基于 VitePress 构建