zoukankan      html  css  js  c++  java
  • HashMap并发下死循环问题解析

    首先小伙伴要明确:死循环问题在JDK 1.8 之前是存在的,JDK 1.8 通过增加loHead和loTail进行了修复。

    在JDK 1.7及之前 HashMap在并发情况下导致循环问题,致使服务器cpu飙升至100%,那么今天就来解析一下线程不安全的HashMap在高并发的情况下是如何造成死循环的。

    要探究hashmap死循环的原因 首先要知道hashmap的源码 这样才能从根本上对hashmap进行理解 。

    首先hashmap进行元素的插入,在元素个数达到阀值时:

    首先小伙伴要明确:死循环问题在JDK 1.8 之前是存在的,JDK 1.8 通过增加loHead和loTail进行了修复。

    在JDK 1.7及之前 HashMap在并发情况下导致循环问题,致使服务器cpu飙升至100%,那么今天就来解析一下线程不安全的HashMap在高并发的情况下是如何造成死循环的。

    要探究hashmap死循环的原因 首先要知道hashmap的源码 这样才能从根本上对hashmap进行理解 。

    首先hashmap进行元素的插入,在元素个数达到阀值时:

    addEntry对判断桶有没有达到阀值,达到阀值就会走resize方法:

    resize方法里调用transfer方法转移元素:

    下面这个方法就是出现死循环的方法了,下面请听我一一道来:

    添加元素达到阀值后对hashmap进行扩容,走reaize方法,在对hashmap进行扩容时,又会调用一个transfer对旧的hashmap中的元素进行转移,那么我们今天要探究的死循环问题 就是发生在这个方法里的,在进行元素转移时transfer方法里会调用下面四行代码 :

        Entry<k,v> next = e.next;
        e.next = newTable[i];
        newTable[i] = e;
        e = next;
    

    把元素插入新的hashmap中,粗略的看下这四行代码 似乎并没有什么问题 元素进行转移的图如下(线程不冲突的情况下):

    那么当多线程(A、B线程)同时访问我们这段代码时:

    现在A线程执行到以下代码时:

        Entry<k,v> next = e.next;
    

    线程A交出时间片,线程B这时候接手转移并且完成了元素的转移,这个时候线程A又拿到时间片并接着执行代码:

     

    执行后代码如图,当e = a时,这时候这时候再执行:

    e.next = newTable[i];// a元素指向了b元素 产生循环
    

    这样链表就就产生了循环,在get元素的时候,线程会一直在环了遍历,无法跳出,从而导致cpu飙升!

    总结:在多线程情况下尽量不要用HashMap,可以用ConcurrentHashMap代替。

    大量面试经验以及学习资料书籍请关注微信公众号:**AVAJ**

    回复"offer"进行获取

    **365篇大厂java面经** 你想要的我这里都有

  • 相关阅读:
    python 模拟浏览器
    转:如何评价架构的优劣
    转:DotNET企业架构应用实践架构师成长之路如何成为优秀架构师
    转:大规模网站架构实战之体系结构(一)
    转:Twitter的设计原则
    转:关于大型asp.net应用系统的架构—如何做到高性能高可伸缩性
    转:我眼中的Visual Studio 2010架构工具
    转:解剖Twitter
    转:Discuz!NT前台模型架构(MVC)
    转: "HTTP 错误 401.1 未经授权:访问由于凭据无效被拒绝"的另类解决方案
  • 原文地址:https://www.cnblogs.com/DoubleP/p/11450408.html
Copyright © 2011-2022 走看看