美文网首页
Jdk1.7下HashMap的头插法问题

Jdk1.7下HashMap的头插法问题

作者: lenny611 | 来源:发表于2019-08-10 12:25 被阅读0次

jdk1.7下,hashmap采用的是头插法,虽然hashmap并不是线程安全的容器,但是在并发情况下,使用hashmap会带来一个问题:

并发情况下,如果插入元素的两个线程都调用了rehash方法,即扩容方法,会导致链表成环的问题。

hashmap成环原因的代码出现在transfer代码中,也就是扩容之后的数据迁移部分(如下):

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;

            if (rehash) {

                e.hash = null == e.key ? 0 : hash(e.key);

            }

            int i = indexFor(e.hash, newCapacity);

            e.next = newTable[i];

            newTable[i] = e;

            e = next;

        }

    }

}

解释一下transfer的过程:

首先获取新表的长度,之后遍历新表的每一个entry,然后每个ertry中的链表,以反转的形式,形成rehash之后的链表。

并发问题:

若当前线程此时获得ertry节点,但是被线程中断无法继续执行,此时线程二进入transfer函数,并把函数顺利执行,此时新表中的某个位置有了节点,之后线程一获得执行权继续执行,因为并发transfer,所以两者都是扩容的同一个链表,当线程一执行到e.next = new table[i] 的时候,由于线程二之前数据迁移的原因导致此时new table[i] 上就有ertry存在,所以线程一执行的时候,会将next节点,设置为自己,导致自己互相使用next引用对方,因此产生链表,导致死循环。

参考:https://blog.csdn.net/qq_32182461/article/details/81152025

HashMap在并发执行put操作时,多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环行数据结构,Entry的next节点永不为空,就会产生死循环获取Entry。

相关文章

网友评论

      本文标题:Jdk1.7下HashMap的头插法问题

      本文链接:https://www.haomeiwen.com/subject/fvaljctx.html