Skip to content
Java 集合与容器 · 第 3 篇 / 共 4 篇
领域编程与框架
专题Java 专题
当前序列Java 集合与容器
阅读位置第 3 篇 / 共 4 篇当前专题第 2 个序列 / 共 10 个序列

HashMap 和 ConcurrentHashMap 怎么选:线程安全、性能与使用边界

HashMapConcurrentHashMap 看起来都像“key-value 容器”,但它们解决的问题并不一样。

很多线上问题并不是因为不会用 Map,而是把“单线程好用”和“并发环境可用”混在了一起。

先说结论

可以先记住这几个判断:

  • 单线程或线程封闭场景,优先 HashMap
  • 多线程共享读写场景,优先 ConcurrentHashMap
  • 不要在并发写入场景下直接使用 HashMap
  • ConcurrentHashMap 解决的是并发访问问题,不代表业务操作天然线程安全

一、HashMap 适合什么场景

HashMap 仍然是最常见的默认 Map 实现。

适合:

  • 方法内临时变量
  • 单线程业务处理
  • 不发生跨线程共享的数据容器

它的优势很直接:

  • API 简单
  • 性能好
  • 使用成本低

但前提是:不要让多个线程同时对它做写操作。

二、为什么并发下不能直接用 HashMap

因为 HashMap 不是线程安全的。

在多线程同时写入时,可能出现:

  • 数据覆盖
  • 结构不一致
  • 读取结果异常

更本质地说,HashMap 根本没有为并发修改提供协调机制。

所以如果某个 Map 是:

  • 静态共享
  • 缓存容器
  • 多线程同时 put / remove / compute

那就不该继续用 HashMap 硬扛。

三、ConcurrentHashMap 解决了什么

ConcurrentHashMap 的目标是:

  • 让并发读写更安全
  • 尽量减少整体锁住整张表的成本

它不是简单地在外面包一层大锁,而是尽可能提高并发访问能力。

所以它特别适合:

  • 本地缓存
  • 并发统计容器
  • 多线程共享配置映射

四、为什么 ConcurrentHashMap 也不是万能的

这是一个特别容易误解的点。

ConcurrentHashMap 保证的是容器级别的并发安全,不代表你在它上面做的复合业务逻辑就一定安全。

例如下面这种“先判断再更新”的逻辑,仍然要小心:

java
if (!map.containsKey(key)) {
    map.put(key, value);
}

因为这本质上是两步操作。

更稳妥的方式通常是考虑:

  • putIfAbsent
  • computeIfAbsent

五、HashMap 和 ConcurrentHashMap 的一个实用判断方式

可以这样简单区分:

用 HashMap

当你能确认:

  • 数据不会跨线程共享
  • 或者已经由更外层同步机制保护

用 ConcurrentHashMap

当你能确认:

  • 这个容器就是多个线程共同访问的共享状态

六、几个高频误区

1. 觉得 ConcurrentHashMap 一定更高级

不是。单线程场景下直接用 HashMap 更自然。

2. 觉得加了 ConcurrentHashMap,整个业务就线程安全了

不是。复合逻辑仍然要自己保证原子性。

3. 觉得只读就无所谓

如果容器初始化完成后完全只读,问题不大;但只要还会并发修改,就要谨慎。

一句话总结

HashMap 解决的是普通映射存储问题,ConcurrentHashMap 解决的是并发共享访问问题。

真正的选型关键不在容器名字,而在于:这个 Map 到底是不是跨线程共享的状态。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读ConcurrentHashMap 原理与使用场景适合把集合选型、ArrayList、HashMap 和 ConcurrentHashMap 放在一条线上理解。Java 专题 · Java 集合与容器同一序列 · 回看前文会更完整ArrayList 为什么仍然是默认首选适合把集合选型、ArrayList、HashMap 和 ConcurrentHashMap 放在一条线上理解。Java 专题 · Java 集合与容器同专题其他序列 · 共享标签:集合、选型对比Collections.synchronizedList 和 CopyOnWriteArrayList 怎么选适合把链表、集合、有序结构、并发容器和迭代语义放到同一条集合主线里看。Java 专题 · Java 集合边界与容器取舍同专题其他序列 · 共享标签:选型对比锁与 CAS 怎么选适合沿着 JUC、volatile、CAS、AQS 和锁实现这条主线往下看。Java 专题 · Java 并发与锁机制跨专题关联 · 同场景:方案选型半同步复制和异步复制怎么选适合把 next-key lock、一致性读、复制延迟和分库分表边界放回同一条一致性主线上判断。MySQL 专题 · MySQL 事务、锁与高可用边界跨专题关联 · 同场景:方案选型分词器、Tokenizer 和 IK 到底怎么选适合把分词、复杂查询和深分页放到一起深入看。Elasticsearch 专题 · Elasticsearch 查询与分析细节
继续阅读Java 集合与容器当前序列第 3 篇 / 共 4 篇当前专题第 2 个序列 / 共 10 个序列
往前看
上一篇ArrayList 为什么仍然是默认首选回到当前序列上一章上一序列Java 语言基础与运行时从第 1 篇开始:String 到底能有多长
往后看
下一篇ConcurrentHashMap 原理与使用场景继续当前序列下一章下一序列Java 并发与锁机制从第 1 篇开始:JUC 总览

把零散经验整理成可查、可复用、可持续更新的企业级知识门户