為什么說HashMap線程不安全呢?
因為並發情況下,HashMap可能造成死循環...
在多線程使用場景中應該盡量避免使用線程不安全的HashMap,可以使用ConcurrentHashMap或者Collections.synchronizedMap().
map初始化為一個長度為2的數組,loadFactor=0.75,threshold=2*0.75=1,所以當put第二個key的時候map就需要resize,然后執行transfer方法,將舊元素進行rehash
下面是transfer方法
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next; //(1)
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i]; //(2)
newTable[i] = e; //(3)
e = next; //(4)
}
}
}
執行以下測試方法
public class DailyTest {
private static HashMap<Integer, String> map = new HashMap<Integer, String>(2, 0.75f);
public static void main(String[] args) {
map.put(5, "C");
new Thread("Thread1") {
public void run() {
map.put(7, "B");
System.out.println(map);
}
}.start();
new Thread("Thread2") {
public void run() {
map.put(3, "A");
System.out.println(map);
}
}.start();
}
}
正常執行過程



並發執行過程
通過設置斷點讓Thread1和Thread2同時Debug到transfer方法的首行,注意此時兩個線程已經成功添加數據,放開Thread1的斷點至transfer方法的Entry next=e.next;這一行,然后放開Thread2的斷點,讓Thread2進行resize

之后Thread1被被調度回來繼續執行后面代碼



至此,HashMap出現了環形鏈表...
