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