HashMap(一)扩容死锁问题分析(JDK1.7)

HashMap扩容死锁问题分析(JDK1.7)

  //JDK1.7扩容源代码
  void transfer(Entry[] newTable) {
        Entry[] src = table;
        int newCapacity = newTable.length;
        for (int j = 0; j < src.length; j++) {
            Entry<K,V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K,V> next = e.next;
                    //重新计算hash值
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }
JDK1.7单线程扩容详解:
  • 假设A、N、M的hash值相同,发生hash碰撞,都放到3这个位置上(此处省略M的插入过程)
  • JDK1.7是采用头插法进行构建链表的,put后的结果如下:


    put数据结果
需要扩容时:
  • 第一次do,while循环


    第一次循环
  • 第二次do,while循环


    第二次循环
  • 第三次do,while循环


    第三次循环
JDK1.7多线程扩容详解:
多线程扩容
  • 假设T1在Entry<K,V> next = e.next;这行失去了CPU使用权。
  • T2继续执行扩容(T2的扩容过程与上诉单线程类似,不同的是T1会保持指针的引用),结果如下:


    T2扩容完成
  • T1开始执行:


    T1开始执行之前的数据结构
  • T1第一次循环后的数据结构


    T1第一次循环后的数据结构
  • T1第二次循环后的数据结构


    T1第二次循环后的数据结构
  • T1第三次循环后的数据结构


    T1第三次循环后的数据结构
  • 当e=null时,T1扩容结束。此时我们可以看出,链表已经成为一个环形。
  • 下次在put数据时,会循环链表查找是否有重复数据。就会形成死循环。

\color{red}{如有不对的地方,欢迎指出。非常感谢!}

\color{red}{原创文章,转载请注明}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。