为什么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这样的死循环。
图片参考:https://blog.csdn.net/qq_23160237/article/details/87883264
上一篇: HashMap为什么线程不安全
下一篇: iOS -- 经典面试题