JDK1.7 HashMap扩容:多线程下的死循环和丢失

多线程情况下,HashMap扩容可能会形成死循环情况,或者丢失值。
假设:
三个Entity,rehash后key值分别为3、5、7。
如图:

《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 init.png

JDK 1.7 HashMap扩容时关键代码:

    void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
        for (Entry<K, V> e : table) {
            while (null != e) {
                Entry<K, V> next = e.next;  // 第5行  关键步骤1
                if (rehash) {
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];  //关键步骤2
                newTable[i] = e;     //关键步骤3
                e = next;            //关键步骤4
            }
        }
    }

请记住上面的4个关键步骤!!!

死循环:

B第一次while循环:

《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 2.png

B第二次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 3.png

B第三次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 4.png

线程B执行完的状态,A恢复执行:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 5.png

线程A开始执行的状态:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 6.png

线程A开始执行第6行,第一次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 7.png

A第二次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 8.png

A第三次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 9.png

线程A执行完,已形成死循环。红线。

值丢失:

更换下三个Entity的顺序,注意如图:

《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 10.png

线程A开始执行:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 11.png

线程A第二次while循环:
《JDK1.7 HashMap扩容:多线程下的死循环和丢失》 12.png

    原文作者:xiaoyiyiyo
    原文地址: https://www.jianshu.com/p/61a829fa4e49
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞