HaspMap 多線程下 resize 死循環

        HashMap在多線程下面出現死循環,這種狀況有點難模擬,千萬別在生成環境出現,一旦出現那就等着哭吧。java

廢話很少說不知道hashmap 如何擴容的先看下源碼可能好理解點。數組

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }
    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable);
    table = newTable;
    threshold = (int) (newCapacity * loadFactor);
}

//此方法就是 hashMap 將數據放到新的擴容以後的數組,方法沒啥問題,徹底正確無誤。
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 {
            //過程(1)
            Entry<K, V> next = e.next;
            int i = indexFor(e.hash, newCapacity);
            e.next = newTable[i];
            newTable[i] = e;
            e = next;
        } while (e != null);
        }
    }
}

在多線程狀況下,狀況就不同了。模擬一種狀況:數據結構

假設如今HashMap 的table 長度爲2 ,因子爲1 以下圖
多線程

現有線程P1 、P2spa

當P1線程執行到 過程(1)下面的時候線程

此時 e =a1 ,next = a2  P2 進入執行了而且執行完畢code

當前新的結構爲索引

再執行P1  此時獲得的新數組索引和P2 是同樣。 ci

e.next =newTable[i] 即爲 a2 (a2.next =a1)源碼

newTable[i] = e 即爲 a1  數組結構變爲

e=next 即爲 a2

第二次循環的時候

Entry<K, V> next = e.next  即爲a1 

e.next = newTable[i]; 即爲 a1 (a1.next = a2)

newTable[i] = e 即爲 a2  數據結構變爲

e=next 即爲 a1

第三次的循環的時候

Entry<K, V> next = e.next  即爲a2

就造成了迴環了。

就成了死循環。

在多線程循環下不要使用hashmap 。

相關文章
相關標籤/搜索