jdk1.7 HashMap 并发情况下不安全 容易造成一个循环列表
本文主要研究在并发的情况下,jdk1.7情况下出现的问题。
在我们使用HashMap的时候,无非就使用put和get方法,并发情况下put的时候就会出现问题。
jdk1.7 put 的源码




hashmap的数据结构是数组和链表的组成,上面的内容大概说的是,当数组不够的时候,要进行X2的扩容。
主要分析transfer的代码。比如原来的table的数,数据key=3,7,5
newTable 新的数组
table:原来的数组

这是出现问题的代码
e.next=newTables[i];
newTables[i]=e;
e=next;
第一步:先分析单线程
1:fo循环第一步:table数组,e=(key=3),next =(key=7),int i=3。hash算法
newTables[3]是null,所以e的next是null。
把e放到了newTables[3]的位置。
next这时变成了key=7。

2:for循环第二步:e=(key7),next =(key5),int i=3
newTables[3]是key(3),所以e的next是key(3)。
把e放到了newTables[3]的位置。
next这时变成了key=5。

3:for循环第二步:e=(key=5),next =null,int i=1
newTables[1]是null,所以e的next是null。
把e放到了newTables[1]的位置。
next这时变成了null。就跳出了循环。

单线程下面HashMap扩容,这是没有问题的。
在分析多线程下面的扩容。
有两个线程,当第一个线程执行到了 Entry<K,V> next = e.next;。由于该线程被挂起,第二个线程直接把扩容的操作进行完了。
直接把table变成了
这时线程1继续往下执行
1:fo循环第一步:table数组,e=(key=3),next =(key=7),int i=3。hash算法
newTables[3]是null,所以e的next是null。
把e放到了newTables[3]的位置。
next这时变成了key=7。

2:fo循环第二步:e=(key=7),next =(key=3),int i=3。hash算法
newTables[3]是key=3,所以e的next是key=3。
把e放到了newTables[3]的位置。
next这时变成了key=3。

3:fo循环第三步:e=(key=3),next =null,int i=3。hash算法
newTables[3]是key=7,所以e的next是key=7。
把e放到了newTables[3]的位置。
next这时变成了null。退出了循环

这个时候就出现了一个死循环的状态。
因为在内存当中,只存在一个对象的实例。key=7实例当中的next指向的是key=3。
而key=3指向的是key=7。从而造成了一个死循环的状态,形成一个循环列表。这也就是jdk1.7中出现的死循环。
在put的时候,并不能体现出来死循环的状态,当get一个不存在的key时候,就容易造成CPU100%

get操作的时候,如果e不等于null,就会一直找下一个next,直到找到为止。
当出现上面的问题,key=3的next指向key=7.而key=7的next指向key=3,CPU就会一直找,形成死循环。
注:上面只是个人的见解,如果有好的见解,往告知,谢谢!

浙公网安备 33010602011771号