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 。

相关文章
相关标签/搜索