HashTable,HashMap,ConcurrentHashMap的区别

一、HashMap

HashMap不适用在多线程里面,因为其本身不带任何锁,多线程操作时是不安全的,而相对安全的HashTable和ConcurrentHashMap是基于HashMap的基础上,通过一定的方式加锁以及相关的优化而得来的。

二、HashTable

HashTable加锁的方式是直接在关键的方法上加synchronized。这就导致只要操作哈希表上的任意元素,都会产生加锁,也就窦娥可能会发生锁冲突。

如上图所示,HashMap表中的所有元素通通用一个大锁锁上,只要一个元素进行操作,其他的就只能阻塞等待。但在实际的开发过程中,有些元素并发执行的时候,并不会产生线程安全问题,不需要锁来进行操作。这就导致该方法在实际的应用中锁冲突的概率太大,即便是不同的链表上的元素进行操作都会有锁冲突。

在进行扩容时,HashTable采用的“中奖机制”。扩容时,创建一个更大的数组空间,把旧的数组上的链表上的每个元素都搬运到新的数组上。而这个操作会在某次put的时候被触发。如果元素个数特别多,就会导致这样的搬运操作比正常的时候耗时更多,体验就是某次put操作完成比平时卡。

三、ConcurrentHashMap

ConcurrentHashMap作为更为优化的线程安全的哈希表,更为推荐使用。首先来了解一下它的加锁方式。

1、相比于HashTable,ConcurrentHashMap将一把大锁转换成了多把小锁。具体表现就是将每个链表都设置一个自己的锁,就是使用每个链表的头结点,作为锁对象。

2、ConcurrentHashMap只针对写加锁,针对读不加锁,但是使用了Volatile来保证线程的安全性。

3、ConcurrentHashMap内部充分的使用了CAS,通过这个也来进一步的削减锁操作的数目。

4、针对扩容,其采取的是“化整为零”的方法。当需要进行扩容的时候,会先创建一个新的更大的数组,同时保留旧的数组,每次进行put操作的时候,都是添加到新的数组上的,同时会搬运一小部分旧数组上的元素到新数组上。每次get操作时,都会考虑到新旧两个数组,每次remove的时候,只要把元素删了就行了。经过一段时间后,所有元素都被搬运完毕,最终释放旧数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值