Hashtable 和 HashMap、ConcurrentHashMap 的对比

目录

一、区别

1. 继承关系

2. 存储的值

3. 线程安全

二、ConcurrentHashMap 相对于 Hashtable 的优化

1. 缩小锁粒度

2. 利用 CAS 特性

3. 优化扩容方式

三、不同版本 ConcurrentHashMap 的自我优化


一、区别

1. 继承关系

HashMap 类继承自 AbstractMap 抽象类
Hashtable 类继承自 Dictionary 抽象类
ConcurrentHashMap 类继承自 AbstractMap 抽象类

2. 存储的值

HashMap 类key 值唯一,可以为 null
Hashtable 类key 值唯一,不可以为 null
ConcurrentHashMap 类key 值唯一,不可以为 null

3. 线程安全

HashMap 类线程不安全,方法没有加锁。
Hashtable 类线程安全,但是是给整个实例对象加锁,访问效率低,Java 官方不推荐继续使用。
ConcurrentHashMap 类线程安全,使用 synchronized 锁每个链表的头节点,锁冲突概率低,性能优于 Hashtable。

二、ConcurrentHashMap 相对于 Hashtable 的优化

1. 缩小锁粒度

  • 读操作没有加锁(但是使用了 volatile 保证从内存读取结果),只对写操作进行加锁;使用 synchronized,但不是锁整个对象,而是锁链表头节点(”锁桶“),大大降低了锁冲突的概率。

2. 利用 CAS 特性

  • 需要经常修改的属性(如 size 等),通过 CAS 更新,避免出现重量级锁。

3. 优化扩容方式

  • 触发扩容后,同时存在新、旧两份哈希表。
  • 插入操作直接往新哈希表中插入。
  • 删除和查询操作会同时操作两份哈希表。
  • 每个参与的线程都负责一部分的元素搬运工作。
  • 扩容完成后,删除旧哈希表,保留新哈希表。

三、不同版本 ConcurrentHashMap 的自我优化

JDK1.7 中的 ConcurrentHashMap加锁使用的是分段锁机制,将哈希桶分成多个段,针对每个段分别加锁。目的是降低锁竞争。Java8 已经不再使用。
JDK1.8 中的 ConcurrentHashMap取消分段锁,给每个哈希桶(链表)分配锁,每个链表的头节点作为锁对象。
底层结构由数组+链表的形式,改进为数组+链表+红黑树,当链表节点数量大于等于8,且数组元素数量大于 64 时,超长的链表转为红黑树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值