ConcurrentHashMap与HashMap的区别?

ConcurrentHashMapHashMap 都是基于哈希表的数据结构,但它们的设计目标和并发行为完全不同。以下是从核心结构、线程安全性、性能、适用场景等方面的对比:


✅ 一、基本区别概览

特性HashMapConcurrentHashMap
是否线程安全❌ 否✅ 是(高并发下仍安全)
并发策略JDK1.7:分段锁JDK1.8:CAS + synchronized
null 键/值是否允许✅ 允许一个 null 键和多个 null 值❌ 都不允许
读写性能(并发场景)低,可能死循环、数据丢失高,并发控制精细
扩容机制是否安全❌ 否✅ 是
JDK 版本支持JDK1.2+JDK1.5+

✅ 二、线程安全性

🔸 HashMap

  • 所有方法都没有同步控制

  • 多线程下可能:

    • 数据覆盖、丢失

    • 链表成环(JDK1.7),导致 get 死循环

    • 非原子操作(如 putIfAbsent)无法保证一致性

🔸 ConcurrentHashMap

  • JDK1.7:

    • 使用 Segment 分段锁(每个 Segment 是一个小 HashMap + ReentrantLock)

    • 并发控制粒度较粗,但较 HashMap 安全

  • JDK1.8(重点):

    • 放弃 Segment,使用:

      • CAS 保证节点插入安全

      • synchronized 替代全锁,锁粒度控制在桶(bin)级别

      • Node<K,V>[] + 链表 + 红黑树结构

    • 并发更高效,读操作多数是无锁的


✅ 三、数据结构差异

JDK 版本HashMap 底层结构ConcurrentHashMap 底层结构
JDK1.7数组 + 链表(头插法)Segment[] + HashEntry 链表
JDK1.8+数组 + 链表 + 红黑树(尾插)Node[] + 链表 + 红黑树 + synchronized + CAS

✅ 四、是否允许 null

null 作为 keynull 作为 value
HashMap✅ 是✅ 是
ConcurrentHashMap❌ 否❌ 否

原因:ConcurrentHashMap 内部使用 null 判断 key 是否存在,加入 null 会破坏语义。


✅ 五、常用场景对比

场景推荐使用
单线程、非并发环境HashMap
多线程读写(高并发)ConcurrentHashMap
Map 需要缓存结构、延迟加载等ConcurrentHashMap(支持原子操作)

✅ 六、API 差异(部分示例)

操作HashMapConcurrentHashMap
putIfAbsent❌ 手动实现✅ 原子操作
computeIfAbsent❌ 需加锁实现✅ 支持并发懒加载
merge✅ 支持
forEach 并发安全遍历✅ 避免 ConcurrentModificationException

✅ 七、小结

对比点HashMapConcurrentHashMap
并发安全❌ 不是✅ 是(读无锁,写粒度细)
并发性能差,多线程容易出错高,适用于高并发缓存/共享结构
null 支持支持 null key 和 null value都不支持,设计上明确拒绝
使用建议单线程或只读环境多线程读写共享结构

如你有意深入了解 ConcurrentHashMap 在 JDK1.8 中的核心实现细节,如 bin 锁设计、红黑树转换、CAS 插入机制等,我可以继续展开。是否需要?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值