[Java 进阶面试题] HashTable, HashMap, ConcurrentHashMap 之间的区别

大家一切顺利~


前言

本篇主要内容如标题


HashTable, HashMap, ConcurrentHashMap 之间的区别

1.ConcurrentHashMap最大优化之处是相比于HashTable,ConcurrentHashMap大大缩小了所冲突的范围,把一把大锁切成了多把小锁.
HashTable的做法是直接在方法上加synchronized,等于直接在this上加锁,只要操作哈希表上的任何元素,都可能产生锁冲突.但实际上,有些元素在并发操作中不会产生锁冲突,不需要这把大锁.
如下图是一个数组,数组的每个元素是一个链表,两个线程分别修改结点1,2,由于1,2有1.next = 2的关系,所以两个线程同时修改这两个节点会有问题,需要锁去控制.但若两个线程同时修改结点3,4,就不会有问题,不需要锁去控制.
在这里插入图片描述
HashTable针对整个数组加一把锁,同时修改任意两个元素都会产生锁冲突.
ConcurrentHashMap是数组中每个链表都有自己的锁,两个线程操作同一链表中的元素会有锁冲突,针对不同链表上的元素就没有锁冲突.
2.ConcurrentHashMap有一个激进的操作,只针对写操作加锁,不对读操作加锁.两个线程同时对一个变量进行读操作或者一个读一个写都不会有锁冲突.
但这样会出现脏读的问题,即一个线程正在读一个变量,而另一线程正在修改这个变量,读到的变量可能是修改之前的数据,是不准确的数据.
解决这个问题的办法是,对可能会被修改的变量进行volatile修饰,将这个变量的写操作设为原子操作,写完之后才允许别的线程去读取这个变量.
3.ConcurrentHashMap内部充分利用了CAS机制,可进一步削减加减操作的数目,比如维护元素个数.
4.进行扩容时,HashMap和HashTable都是先创建更大的数组空间,把旧数组上的每个元素搬到新数组上.所以,当数组满需要扩容的时候,再次put(),会发现这次put非常卡.
ConcurrentHashMap扩容方法是,创建新数组,旧数组先保留,之后每次进行put()操作时,把要添加的元素put到新数组上,把旧数组上的一部分元素搬到新数组上.进行get()操作的时候,旧数组和新数组都要去查询.每次move()的时候,把元素直接删除即可.
等到旧数组上的元素全都被搬到新数组上,就可以释放
旧数组了.

本文结束


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值