JDK1.7HashMap 为什么会产生死循环

JDK1.7 HashMap为什么会产生死循环

1. 大家没有想到吧,在jdk1.7中HashMap会有死循环的场景出现,当然前提是在并发的情况下,单线程操map是不会有死循环问题的,那HashMap死循环是怎么产生的呢? 先给出结论,在并发下对同一个map进行操作,当map进行扩容的时候就有可能会产生循环依赖疑问,当有调用map的get()方式的时候由于里面存在循环引用就会导致CPU一直到100%,碰到这种情况就只能服务重启了,所以现在大家的项目中一般都使用JDK1.8,有了结论下面我们来一起分析并发下死循环是怎样产生的

2. 上面提到了产生死循环的前提是在并发下给map集合put()数据的时候,集合需要扩容就有可能产生,我们一起来看下扩容的代码

3. 这里面大家一定要了解java里面的引用,假设有一个如下集合 Entry<K,V> next = e.next; B线程也执行扩容操作,此时A线程被挂起

当然在左右的集合里面 0 的位置也存在很多数据,1的位置也还有其它的数据,这里为了简化分析就不列出来了,这时候

如果有A,B两个线程来向map里面put()数据,这时候map进行扩容,当 A线程执行到 Entry<K,V> next = e.next 时候B线程也

进入执行扩容,此时A线程如果被挂起了。当B线程执行完后已经将数据扩容了,这时A线程是不知道B线程的执行任务的,

没有感知的,此时的数据结构图

A线程在来执行下面的代码(key(5) 这里就不做分析了) 此时 key(7) .next = key(3)   (根据下面的代码应该可以看出扩容时使用的是头插法吧), A线程执行完挂起的时候是 next = key(7), e = key(3),  e.next = newTable[3], 现在A线程操作的table里面

是空的 ,也就是得到的结果 key(3).next = null 的 (大家需要认真思考哦这块还是比较难的)newTable[3] = key(3),  e=next

(e = next 就是为了 while( null != e ) 就是链表的遍历方式,一直遍历到最后一个节点 ),此时的 e = key(7), 又来执行下面

的代码, next = e.next  [由于在线程B中 将  key(7) -> key(3) 这是死循环产生的很重要的原因如果没有B线程的修改这时候 key(7).next == null 的], 此时 next = key(3) (这里面应该记得在上面的循环中 key(3).next == null 的 table[3] = key(3)),  e = key(7)

再执行下面代码, e.next = newTable[i] 实际就是 key(7).next = key(3), newTable[i] =key(7) (现在在newTable 里面的数据结构是 key(7) -> key(3)),  在执行 e = next  得到 e = key(3),  再进入while(null != e) 的循环, next = key(3).next 得到 next = null, e.next = newTable[i],--> key(3).next = key(7), newTable[3]=key(3) 死循环就出来了 key(3).next = key(7), key(7).next = key(3), 之这样如果查询一个不在map中的table[3]位置的数据就会进入死循环, 代码接着往后面看, e = next  由于 next 为 null 所以 e = null; while(null != e) 不成立,跳出循环了,到这里整个产生死循环的代码就分析完了。 读者如果一遍看不懂是很正常的现象,代码的逻辑切换还是很强的,一不留神就会晕车,笔者在阅读这段源码的时候也有晕车现象,但是笔者在这里已经讲的很详细了,相信读者按照上面的逻辑步骤反复的读一定能够理解的, 源码没有简单的 冲鸭!!!

最终结果图

作为一名负责人的博主 在这里 我特别说明点 是在A线程执行完 Entry<K,V> next = e.next 后线程被挂起了 B线程完成了扩容后,

A线程再接着唤醒执行 , 此时的 B 线程 已经将 key(7).next = key(3) 了, 而在 A线程里 被唤醒时候 e = key(3), next= key(7)的,

核心代码截图如下, 通过代码的阅读也可以看到不是什么时候都会产生死循环的,但是一旦产生就只能服务重启,所以如果你们的项目中使用了的是JDK1.7而且有并发操作map的问题建议升级JDK到1.8。

 

如果读者通过阅读有收获就点个赞呗,原创不易,关注博客后面持续分享跟多精彩内容,

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值