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出现了环形链表...