zoukankan      html  css  js  c++  java
  • 不一样的内容:死磕JDK8中ConcurrentHashMap.computeIfAbsent 死循环 Bug

    背景:

       最近有朋友提到了JDK1.8中的ConcurrentHashMap有可能引起CPU飙升的问题,立马恶补,因为运行的生产环境就是1.8版本的,希望没有采坑。

    浏览后,发现网上文章千篇一律,不全面。经过一上午的分析、研究,总结如下,共同进步~~~~~~~~~~~~

    之前文章中提到过《JDK1.7中HashMap引起CPU100%的问题》,那么JDK8中的ConcurrentHashMap也不一定是安全的。
    官方Bug报告: https://bugs.openjdk.java.net/browse/JDK-8062841
    JDK9中变化内容: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/6dd59c01f011

    再次描述下这个bug,运行如下程序

    Map<String, Integer> map = new ConcurrentHashMap<>();
    map.computeIfAbsent("a", key -> {
        map.put("a", 2);
        return 1;
    });

    JDK1.8中 computeIfAbsent 部分代码

    ReservationNode 在 computeIfAbsent() 方法构建 value 值的时候被用作占位节点。换句话说,computeIfAbsent() 方法会初始化一个 ReservationNode 来占位,它会等待计算完毕后替换当前的占位对象。此时,如果正好赶在 ConcurrentHashMap 达到容量 0.75 的时候进行扩容,由于ConcurrentHashMap 扩容忽略了 ReservationNode 情况。调用put的时候在synchronized (f)没有对ReservationNode处理,所以会出现死循环。因此,可能会导致扩容无法替换占位符,同时占位符等待替换的情况,然后就一直 for 循环处理了。

    这也是为什么网上很多人说,如果不存在递归调用computeIfAbsent()是不会发生的。

    ==========================================================================           如果您觉得这篇文章对你有帮助,可以【关注我】或者【点赞】,希望我们一起在架构的路上,并肩齐行
    ==========================================================================
  • 相关阅读:
    111
    ZeroClipBoard 复制粘贴插件
    三、新增临时素材
    二、获取AccessToken
    一、微信公众平台的接入微信公众平台的接入
    Jquery.validate的使用
    尝试解决IIS问题一些方法
    匿名类和匿名方法
    泛型类的认知
    发布支持mysql8.0的writer和reader
  • 原文地址:https://www.cnblogs.com/amberJava/p/13065015.html
Copyright © 2011-2022 走看看