HashMap、Hashtable、ConcurrentHashMap之间的区别

目录

一、Hashtable

二、ConcurrentHashMap

1、锁粒度的控制

2、读操作不加锁 

3、利用了CAS的特性

4、优化扩容操作

三、区别:


一、Hashtable

Hashtable虽然是线程安全的,但是它只是简单地用synchronized修饰了一些关键方法,相当于是对this加锁,即对整个Hashtable对象进行加锁!

在多线程环境下,这种“无脑”的加锁方式是非常低效的:

(1) 多个线程访问同一个Hashtable对象时,无论做什么操作,都会产生锁冲突;

(2) 如果某个线程触发了扩容机制,那么就会由这个线程完成整个扩容过程,如果元素过多,效率则非常低,其它线程阻塞等待的时间也会更长。

Java官方已经不推荐使用Hashtable了~

二、ConcurrentHashMap

ConcurrentHashMap相较于Hashtable做了许多的优化,核心思路就是降低锁冲突概率~

1、锁粒度的控制

ConcurrentHashMap不是锁整个对象,而是使用多把锁,对每个链表(哈希桶)都进行加锁,只有当两个线程同时访问同一个链表时,才会产生锁竞争,因此极大地降低了锁冲突的概率。

2、读操作不加锁 

ConcurrentHashMap只对写操作进行加锁,读操作没有加锁,此时会有三种情况:

(1) 两个线程同时修改一个哈希桶时才会产生锁冲突;

(2) 两个线程同时读数据,不会有锁冲突;

(3) 一个线程修改,一个线程读,也没有锁冲突。

第三种情况可能会有线程不安全问题,这和我们写的代码有关,但是ConcurrentHashMap中的读操作使用了Volatile,来保证读到的数据不是修改了一半的数据。

3、利用了CAS的特性

ConcurrentHashMap充分利用了CAS的特性,避免出现重量级锁的情况。

比如维护元素个数(size)时,就是通过CAS来更新~

4、优化扩容操作

Hashtable的扩容机制是,创建一个更大的新数组,然后由一个线程一次性把旧数组中的元素搬运到新数组。

ConcurrentHashMap则是让新数组和旧数组同时存在一段时间,在这期间,后续每个操作ConcurrentHashMap的线程都会负责搬运旧数组的一部分元素到新数组,直到搬运完旧数组的最后一个元素时,再把旧数组删除~

搬运期间,插入元素时直接插入到新数组中;查询元素时,新数组和旧数组一起查。

三、区别:

1、HashMap线程不安全,适用于单线程环境,key值可以为null;

2、HashTable线程安全,但锁的是整个Hashtable对象,效率较低,key值不可以为null;

3、ConcurrentHashMap线程安全,锁的是每个链表的头结点,降低了锁冲突的概率;充分利用CAS机制;优化了扩容方式;key值不可以为null,适用于多线程环境。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃点橘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值