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已經成為閉環了。
總結:一個執行緒在記錄順序的地方停了,而另一執行緒卻把這個順序反反轉了,當停止的執行緒再次執行的時候,本來該指向下游的指標,指向了上游,就成了閉環,形成了死迴圈。