HashMap为什么不是线程安全的

1 HashMap为什么不是线程安全的

以JDK1.8的HashMap为例
在这里插入图片描述
造成线程不安全的方法主要是**resize(扩容)**方法

情况一:数据直接覆盖

线程A线程B 同时对同一个HashMap进行PUT操作,假设A和B插入的Key-Value中key的hashcode是相同的,这说明该键值对将会插入到Table的同一个下标的,也就是会发生哈希碰撞,此时HashMap按照平时的做法是形成一个链表(若超过八个节点则是红黑树),现在我们插入的下标为null(Table[i]==null)则进行正常的插入,此时线程A进行到了这一步正准备插入,这时候线程A堵塞,线程B获得运行时间,进行同样操作,也是Table[i]==null , 此时它直接运行完整个PUT方法,成功将元素插入. 随后线程A获得运行时间接上上面的判断继续运行,进行了Table[i]==null的插入(此时其实应该是Table[i]!=null的操作,因为前面线程B已经插入了一个元素了),这样就会直接把原来线程B插入的数据直接覆盖了,如此一来就造成了线程不安全问题.

情况二:resize的时候造成的

现在假设HashMap中的Table情况如下:
在这里插入图片描述
线程A和线程B要对同一个HashMap进行PUT操作.插入后Table变为:
在这里插入图片描述
此时,线程A和B都需要对HashMap进行扩容,假设线程A没有堵塞过,顺利完成resize后Table如下(这里的元素位置都是假设的):在这里插入图片描述

如果线程B的resize是在Entry3的时候堵塞的,那么当它再次执行的时候就会造成在这里插入图片描述
处形成一个循环链表,当进行get操作时候可能陷入死循环,原因是:**线程B获得CPU时 e = Entry3 , next = Entry2 正常赋值,**然后进行下一次循环遍历时要注意,此时HashMap已经被线程A resize 过得了,那么就有 e = Entry 2 , next = Entry3 头插法插入此时:在这里插入图片描述
,接着循环,e = Entry 3 ,next = Entry3.next = null (看图) ,此时再时候头插法就会形成循环链表了在这里插入图片描述
附上头插法代码:在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值