HashMap死循环记录

0.jdk1.7

1.查看HashMap的源码,了解其结构和实现原理

2.单线程的时候,不会造成死循环

3.多线程的时候,当两个线程都在扩容的时候,一个 线程挂起,另一个已经完成,挂起的那个在扩容的时候会和第二个线程的数据死循环

4.死循环,原因。可能主主存和缓存的运营。每个线程都有自己的缓存,entry的e和next指针都在缓存里。当一个线程完成扩容,entry的顺序已经倒置,因为顺序变了,就刷新了主存的顺序。当第二挂起的线程,在执行的时候,先恢复挂起的顺序,当执行完正常的流程的时候,它回去主存里取数据,主存里的顺序是线程一修改的,两个线程顺序互相指向对方,死循环开始。

5.线程1和线程2执行以下代码 map里里面的是三个数3,7,5,初始个数是2,当3个就会扩容,执行以下代码

1.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;

线程1停到了1的地方,map的顺序还是3->7->5  自己的newTable为空

线程2开始执行,map的顺序反转变成   5-null;自己的newTable已赋值,并且把newTable的值赋给table。

                                                              7->3->null;

这时候线程一开始执行

循环一次:

当前e=3

next=3.next=7;因为停到了这里,所以线程一去到的数字顺序还是之前的顺序,其实已经被线程2改变了。

3.next=newTable[i]=null

newTable[i]=3;

e=next=7;

循环二次:

当前e=7

next=7.next=3;这时候取值是是从线程2改变的map里取值的,这里取得值已经是改变了的table,所以7的下next指向了3

7.next=newTable[i]=3;因为上一步已经把3放进去了

newTable[i]=7;把7也放进去了

e=next=3;

循环三次:

当前e=3

next=3.next=null;还是线程2 的顺序了;

3.next=newTable[i]=7;

newTable[i]=3;

e=next=null;

e=null,循环停止;但循环2和循环3的时候,绿色文字,3和7已经成为闭环了。

总结:一个线程在记录顺序的地方停了,而另一线程却把这个顺序反反转了,当停止的线程再次运行的时候,本来该指向下游的指针,指向了上游,就成了闭环,形成了死循环。

                

猜你喜欢

转载自blog.csdn.net/csdn_littlefish/article/details/75370553