HashMap在java併發中如何發生死迴圈

2021-09-02 12:25:27 字數 2455 閱讀 5607

在多執行緒環境中,使用hashmap進行put操作時會引起死迴圈,導致cpu使用接近100%,下面通過**分析一下為什麼會發生死迴圈。

static class entryimplements map.entry

、 }

/**

* the table, resized as necessary. length must always be a power of two.

*/transient entry table;

之所以會導致hashmap出現死迴圈是因為多執行緒會導致hashmap的entry節點形成環鏈,這樣當遍歷集合時entry的next節點用於不為空,從而形成死迴圈

單新增元素時會通過key的hash值確認鍊錶陣列下標

public v put(k key, v value) 

}modcount++;

//新增鍊錶節點

addentry(hash, key, value, i);

return null;

}

下面看一下hashmap新增節點的實現

void addentry(int hash, k key, v value, int bucketindex)
以上部分的實現不會導致鏈路出現環鏈,環鏈一般會出現hashmap擴容是,下面看看擴容的實現:

void resize(int newcapacity) 

entry newtable = new entry[newcapacity];

transfer(newtable);//可能導致環鏈

table = newtable;

threshold = (int)(newcapacity * loadfactor);

}

下面transfer的實現

void transfer(entry newtable)  while (e != null);}}

}

這個方法的目的是將原鍊錶資料的陣列拷到新的鍊錶陣列中,拷貝過程中如果形成環鏈的呢?下面用乙個簡單的例子來說明一下:

public class infiniteloop ;

}.start();

new thread("thread2") ;

}.start();}}

下面通過debug跟蹤除錯來看看如果導致hashmap形成環鏈,斷點位置:

執行緒1的put操作

執行緒2的put操作

執行緒2的輸出操作

hashmap原始碼transfer方法中的第一行、第六行、第九行

測試開始

使執行緒1進入transfer方法第一行,此時map的結構如下

2.  使執行緒2進入transfer方法第一行,此時map的結構如下:

3.接著切換回執行緒1,執行到transfer的第六行,此時map的結構如下:

4.然後切換回執行緒2使其執行到transfer方法的第六行,此時map的結夠如上

5.接著切換回執行緒1使其執行到transfer方法的第九行,然後切換回執行緒2使其執行完,此時map的結構如下:

6.切換回執行緒1執行迴圈,因為執行緒1之前是停在hashmap的transfer方法的第九行處,所以此時transfer方法的節點e的key=3,e.next的key=7

void transfer(entry newtable)  while (e != null);}}

}

下面執行緒1開始執行第一次迴圈,迴圈後的map結構如下:

接著執行第二次迴圈:e.key=7,e.next.key=3,e.next.next=null

接著執行第三次迴圈,從而導致環鏈形成,map結構如下

並且此時的map中還丟失了key=5的節點

java中怎麼遍歷HashMap

1.hashmap staff new hashmap 新增關鍵字值對,自己寫遍歷 set entries staff.entryset iterator iter entries.iterator while iter.hasnext 2.map map new hashmap for itera...

java中hashmap的作用

就是乙個鍵值對應的集合 hashmap a new hashmap a.put name abcdef key是name,value是字串abcdef system.out.println a.get name 根據key取得其值並輸出 list list new arraylist list.ad...

HashMap基礎與併發

執行緒不安全的hashmap,hashmap在併發執行put操作時會引起死迴圈,是因為多執行緒會導致hashmap的entry鍊錶形成環形資料結構,查詢時會陷入死迴圈。預設初始化大小為16,之後每次擴充,容量變為原來的2倍 預設載入因子為0.75 modcount作用 迭代器每修改一次就 1 has...