您的位置:首页 > 其它

HashMap在并发环境下发生死循环

2016-09-20 14:36 225 查看
HashMap不是线程安全的,在高并发的某种情况下会发生死循环,主要是在HashMap扩容时的 transfer方法出现了问题:

/**
     * Transfers all entries from current table to newTable.
     */
    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;//(1)
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }
    }



两个线程P1和P2都走到这个方法,执行方法前链表数据如下:

P1:a->b->c->d->null

P2:a->b->c->d->null

线程按一下顺序执行:

1. P1第一次执行到(1)处时阻塞,此时 next 的值是b ,e的值是a;

2. P2执行完整个流程,此时链表在newTable中可能变成如下情况:

b->a

c

d

3. P1继续执行,以下代码中newTable[i]是P2执行完的链表第一个元素b,执行完以下代码会导致a->b,而在新的一轮循环中,b.next是a,死循环产生;

e.next = newTable[i];
newTable[i] = e;


死循环产生的必要条件(欢迎指正):

1. 原索引数组的某个链表中的有两个元素A,B相邻

2. A,B被转到新的索引数组的同一个链表,即索引值相同

3. 高并发
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息