zoukankan      html  css  js  c++  java
  • HashMap的死锁 与 ConcurrentHashMap

    HashMap

    Java7,HashMap 会产生死锁;  数据模型:数组 + 链表

    Java8,HashMap 不会产生死锁,同时put有可能会产生数据丢失的情况;数据模型:数组 + 链表 + 红黑树

    JAVA7 HashMap死锁的原因:hashMap在多线程的场景下,扩容期间存在节点位置互换指针引用,有可能导致死环;

    扩容的阈值:threshold = 16 * 0.75,超过阈值就会去扩容。

    java7 的 HashMap 的 resize() 方法:

    void resize(int newCapacity) {   //传入新的容量
        Entry[] oldTable = table;    //引用扩容前的Entry数组
        int oldCapacity = oldTable.length;         
        if (oldCapacity == MAXIMUM_CAPACITY) {  //扩容前的数组大小如果已经达到最大(2^30)了
            threshold = Integer.MAX_VALUE; //修改阈值为int的最大值(2^31-1),这样以后就不会扩容了
            return;
        }
     
        Entry[] newTable = new Entry[newCapacity];  //初始化一个新的Entry数组
        transfer(newTable);                         //!!将数据转移到新的Entry数组里
        table = newTable;                           //HashMap的table属性引用新的Entry数组
        threshold = (int)(newCapacity * loadFactor);//修改阈值
    }
    

    transfer方法:

    void transfer(Entry[] newTable) {
         Entry[] src = table;                   //src引用了旧的Entry数组
         int newCapacity = newTable.length;
         for (int j = 0; j < src.length; j++) { //遍历旧的Entry数组
             Entry<K,V> e = src[j];             //取得旧Entry数组的每个元素
             if (e != null) {
                 src[j] = null;//释放旧Entry数组的对象引用(for循环后,旧的Entry数组不再引用任何对象)
                 do {
                     Entry<K,V> next = e.next;
                     int i = indexFor(e.hash, newCapacity); //!!重新计算每个元素在数组中的位置
                     e.next = newTable[i]; //标记[1]
                     newTable[i] = e;      //将元素放在数组上
                     e = next;             //访问下一个Entry链上的元素
                 } while (e != null);
             }
         }
    }
    

      

    ConcurrentHashMap

    Java7, Segment 继承 ReentrantLock

     Java8,synchronized加锁,使用 CAS

     

    Java1.7 HashMap死锁的原因:hashMap在多线程的场景下,扩容期间存在节点位置互换指针引用,有可能导致死环;

    扩容的阈值:threshold = 16 * 0.75,超过阈值就会去扩容。

  • 相关阅读:
    发一个使用 GridView 对数据小类进行分别汇总的例子
    C#根据当前时间确定日期范围(本周、本月、本季度、本年度)
    软件开发人员的作战手册
    C#服务常用继成函数说明
    ServiceController控制windows服务
    不做沙和尚
    C#多线程(二) 如何操纵一个线程转
    C#多线程(一) 多线程的相关概念
    如何为windows服务添加安装程序(转)
    用C#开发Windows服务、自动安装注册(转)
  • 原文地址:https://www.cnblogs.com/yufeng218/p/13211236.html
Copyright © 2011-2022 走看看