JDK1.7 HashMap死循环问题
为什么说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出现了环形链表...

浙公网安备 33010602011771号