HashMap详解(三)

上一篇分析的扩容是基于JDK1.8,当发生哈希碰撞的时候采用尾插法,并会动态决定用红黑树和链表来串,但是我们还是有必要了解一下,简单来说:
HashMap在多线程操作的时候,由于碰撞的时候链表采用头插法,线程A执行put的时候发现需要扩容,走到一半挂起,线程B也去put发现需要扩容,则resize,rehash一顿操作并把位置放好了,此时A线程拿到时间片操作也是一顿操作,此时出现同一index的第一个和第二个键值对相互指向,形成循环链表,此时get(第一个key)和get(第二个key)其实也都是没问题的,直到get(key)某一个key的时候散列到当前的index 并且不存在当前index上的链表上,此时出现死循环。
于是出现了ConcurrentHashMap

ConcurrentHashMap(JDK1.7)

在这里插入图片描述
如图所示,是由 Segment 数组、HashEntry 数组组成,和 HashMap 一样,仍然是数组加链表。

HashEntry和Entry唯一的区别就是其中的核心数据如 value 、next都是 volatile 修饰的,保证了获取时的可见性。

原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。

ConcurrentHashMap(JDK1.8)

在这里插入图片描述
看起来是不是和 1.8 HashMap 结构类似?

其中抛弃了原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性
put方法可以参照上一篇文章,另外HashEntry也被替换成了Node,但作用相同,get的时候都是通过内部成员变量保证获取最新的,所以像put一样加锁,提高了效率。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Alex_ChuTT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值