【Java EE】-多线程编程(十) HashMap&&HashTable&&ConcurrentHashMap之间的区别

作者:学Java的冬瓜
博客主页:☀冬瓜的主页🌙
专栏【JavaEE】
分享
主要内容:HashMap和HashTable之间的区别、HashTable和ConcurrentHashMap之间的区别、

一、HashMap和HashTable的区别

HashMap是线程不安全的
而HashTable是线程安全的,因为HashTable所有方法都加上了synchronized,是串行(同步的)。

二、HashTable和ConcurrentHashMap之间的区别

1、最大的优化之处:ConcurrentHashMap比HashTable大大降低了锁冲突

我们知道哈希表可以使用闭散列(开放地址法)和开散列(链地址法)解决哈希冲突,但是一般都是使用链地址法,也称为哈希桶。
哈希桶是使用数组 + 链表的方式组织起来。

对于HashTable来说,它的加锁是直接加上一个大锁,把整个数组+链表的操作用一把锁加锁,这会导致性能问题。比如多个线程修改一个链表上的数据时,会有线程安全问题,所以一个线程先修改,其它线程阻塞等待,这时候是没毛病的;但是如果是多个线程修改不同链表上的节点时,因为不可能找到同一个节点,没有线程安全问题,所以这个大锁就没必要加上了,加了锁,会有锁冲突,反而会降低效率。因此ConcurrentHashMap就给我们做了优化。

对于ConcurrentHashMap来说,相对于HashTable来说,ConcurrentHashMap减小了锁的粒度。在JDK1.7之前,它是使用"区间锁"(给几个链表加一个锁)的方式降低锁冲突,从而提高并发效率。在JDK1.8及之后,就给每个链表加上锁,这样就可以完美解决使用HashTable时的线程安全问题和性能问题。

2、ConcurrentHashMap只对写加锁 并使用volatile+原子的修改提高性能

HashTable是对每个方法都加锁

ConcurrentHashMap不对读加锁,只针对写加锁。
但是这样的话,多线程读没问题;多线程写,因为加锁了,无线程安全问题;多线程读和写,就有线程安全问题,可能会出现类似"脏读"的问题。
因此ConcurrentHashMap就再加上了另外一个策略:volatile和写操作原子。

3、ConcurrentHashMap内部使用了大量的CAS,从而提高并发效率

Concurrent内部充分利用了CAS,削减锁操作,从而提高效率

4、ConcurrentHashMap扩容使用"慢慢搬"的策略

在HashMap和HashTable中,插入元素,在某一次put操作,当达到扩容的条件时,会重新申请一个空间,然后把旧数组中的每个元素一个一个重新哈希转移到新数组这里。也就是说,如果数据量很大很大时,会可能存在在某一次put时,会卡一段时间的问题。

而ConcurrentHashMap对上面的场景做了优化,它使用 “慢慢搬” 的策略,即插入元素,在某一次put操作时,满足扩容条件时,先申请一个数组空间,然后先把旧数组中的元素 “搬一些” 到新数组,在每次put的时候都 “搬一点”,如果在 “搬运元素” 期间,需要get操作取数据,就从旧数组和新数组中都找。直到最后一次put时,元素 “搬运” 完,旧的数组 + 链表的全部元素都重新哈希到新的数组 + 链表的结构当中了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学Java的冬瓜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值