HashMap 与 ConcurrentHashMap 有什么区别?

考查重点:并发访问与复合操作原子性。HashMap 不保证并发安全,ConcurrentHashMap 支持并发操作;复合读改仍用 compute 等原子接口,迭代语义也不同

本题目录

参考答案

核心回答

HashMap 是普通的哈希映射,适合线程内使用,或由外部统一保证同步的场景;ConcurrentHashMap 是为共享并发访问设计的映射,提供线程安全的查询、更新及部分原子复合操作。下面以 Java 25 的行为为准。

主要区别有四点:

  • 并发保证不同。 HashMap 自身不做同步,并发读写可能丢失更新、读取不一致;ConcurrentHashMap 对容器操作提供相应的并发保证,普通查询一般不阻塞,可以与更新重叠进行。
  • 实现方式不同。 两者都使用哈希桶,并可用链表或树处理冲突,但 ConcurrentHashMap 还通过具有可见性保证的访问、CAS、桶级同步及协作扩容协调并发,而不是给所有操作加一把全局锁。
  • null 约定不同。 HashMap 允许 null 键和 null 值;ConcurrentHashMap 都不允许,使查询返回 null 可以明确表示没有映射。
  • 遍历语义不同。 HashMap 的迭代器对违规结构修改采用尽力而为的 fail-fast 检测;ConcurrentHashMap 的迭代器弱一致,允许遍历期间发生更新,不提供整张表的同一时刻快照。

多线程共享且需要频繁独立读写时,通常选 ConcurrentHashMap;线程内临时数据用 HashMap 更直接。但容器线程安全不等于整个业务操作自动原子。

ConcurrentHashMap 为什么能支持并发

普通 HashMap 的插入、链表修改、计数和扩容没有并发协调。以 OpenJDK 25 实现为例,ConcurrentHashMap 对空桶插入尝试 CAS,有冲突的普通更新在桶首节点上同步,并在获得锁后重新检查桶状态。不同桶的更新因此可以并行推进,同一桶内仍可能竞争。

节点字段及桶位访问的内存语义保证了必要的发布与可见性。某个键的更新,与读取到该更新值的查询之间存在 happens-before 关系;这不代表一次遍历或多次 get 能看到全表统一快照。

版本也要区分:JDK 7 的 ConcurrentHashMap 使用 Segment 分段锁;JDK 8 已改为桶数组、CAS 和桶级同步等机制,不能把 Segment 模型套到后续版本,也不能因为有 CAS 就称整个容器“无锁”。

为什么 get 后再 put 仍可能出错

假设两个线程都读取某商品浏览数为 10,各自加一后写回 11。每次 get、put 都安全,最终仍只增加了一次,因为“读、计算、写”不是一个原子操作。可以根据语义使用 merge、compute 或专门的并发计数器;“不存在才创建”可以使用 putIfAbsent、computeIfAbsent。

这类原子操作也有范围。computeIfAbsent 的计算函数应短小,不能在其中递归修改这张表;长时间远程调用可能阻塞其他相关更新。某个键被删除、计算返回 null 或失败后,后续仍可能重新计算,不能把它当成业务动作终身只执行一次的保证。

如果值是可变的 ArrayList,把它放进 ConcurrentHashMap 并不会让列表自身变成线程安全;拿到列表后并发修改仍需另行协调。转账等跨多个键的不变量也需要更大范围的同步或事务设计。

追问:能不能给 HashMap 加锁

可以,例如使用 Collections.synchronizedMap,或者让所有相关读写遵循同一把外部锁;遍历同步包装后的 Map 也要按其约定持锁。只锁写入、查询却绕过同步,不能普遍保证安全。初始化后不再修改且安全发布的只读 HashMap,则可以供多个线程读取。

如果需要在同一把锁下原子检查多项状态,统一加锁有其价值;如果大量操作只涉及独立键,ConcurrentHashMap 通常提供更细的并发粒度。两者的选择取决于业务原子性和竞争形态,不能用固定性能倍数判断。

参考资料

相关面经

7 篇

曹操出行

后端实习
实习
查看原面经 →
concurrentHashMap比HashMap优点,解决了什么问题,底层怎么实现的

去哪儿

AI 应用开发
查看原面经 →
hashmap是线程安全的吗,concurrenthashmap在jdk8中是如何实现线程安全的?

百度

后端开发工程师
一面
查看原面经 →
HashMap底层实现原理是什么?数据结构是怎么样的?是否线程安全?不使用ConcurrentHashMap、HashTable这种已有实现,你会如何改进现有的HashMap实现线程安全?

去哪儿

测试开发工程师
一面
查看原面经 →
HashMap和ConcurrentHashMap的原理与区别?

招银科技

后端开发工程师(AI / Agent 方向)
社招
查看原面经 →
Hashmap concurrenthashmap区别
展开剩余 2 篇面经

快手

后端开发工程师
校招春招一面、二面、三面
查看原面经 →
HashMap和ConcurrentHashMap区别

法大大

Java 开发工程师
实习一面
查看原面经 →
ConcurrentHashMap和HashMap有什么区别

收录题集

1 个来源,共1 份题集

系统设计与后端基础

阿东玩 AI · AgentGuide · 1 条原题

查看题集 →

相关题目

4 题