欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

为什么HashMap线程不安全

程序员文章站 2022-04-14 22:54:40
...

1.put操作时导致多线程数据不一致

当有多个线程进行put操作时
假设现在有两个线程A跟B进行put操作,线程A已经计算完要放入记录的桶的索引坐标,但是还没有将记录插到桶里面时A的时间片就已经用完,
然后轮到线程B执行,假设B的索引坐标跟A的一样,不同点是线程B成功插入记录,那么线程A再次被调度运行时,所用的索引坐标跟线程B的索引坐标一样,线程A将记录插入之后,就会把线程B插入的记录覆盖掉,因此会产生数据不一致。

2.可能因为resize而引起死循环。

resize机制:
HashMap的扩容机制就是重新申请一个容量是当前的2倍的桶数组,将原先的记录逐个重新映射到新的桶里面,然后将原先的桶逐个置为null使得引用失效。

以jdk1.7的代码为例:

voidtransfer(Entry[] newTable)
{
    Entry[] src = table;
    intnewCapacity = newTable.length;
    //下面这段代码的意思是:
    //  从OldTable里摘一个元素出来,然后放到NewTable中
    for(intj = 0; j < src.length; j++) {
        Entry<K,V> e = src[j];
        if(e != null) {
            src[j] =null;
            do{
                Entry<K,V> next = e.next;
                inti = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            }while (e != null);
        }
    }
}

假设Hash表的size=2, 有三个键值对,key分别为 3, 7, 5,在进行冲突处理之后都存储在table[1]。
当前有两个线程,线程一,线程二。
假设线程一执行到next = e.next这段代码之后时间片用完,然后执行线程二,此时线程一的e对应key为3 next对应key为7
执行完线程二(如下图所示),线程二顺利完成resize操作。
此时key为7的next为key为3。
再执行线程一的时候就会产生3 ->7->3这样的死循环。

为什么HashMap线程不安全
图片参考:https://blog.csdn.net/qq_23160237/article/details/87883264

相关标签: 并发编程