更多博客请见 我的语雀知识库


默认此情况仅发生在1.7版本下并发对哈希表扩容的情况下

第一步:线程启动,有线程T1和线程T2都准备对HashMap进行扩容操作, 此时T1和T2指向的都是链表的头节点A,而T1和T2的下一个节点分别是T1.next和T2.next,它们都指向B节点。

第二步:开始扩容,这时候,假设线程T2的时间片用完,进入了休眠状态,而线程T1开始执行扩容操作,一直到线程T1扩容完成后,线程T2才被唤醒。


T1完成扩容之后的场景就变成动画所示的这样。

因为HashMap扩容采用的是头插法,线程T1执行之后,链表中的节点顺序发生了改变。但线程T2对于发生的一切还是不可知的,所以它指向的节点引用依然没变。如图所示,T2指向的是A节点,T2.next指向的是B节点。

当线程T1执行完成之后,线程T2恢复执行时,死循环就发生了。


因为T1执行完扩容之后,B节点的下一个节点是A,而T2线程指向的首节点是A,第二个节点是B,这个顺序刚好和T1扩容之前的节点顺序是相反的。T1执行完之后的顺序是B到A,而T2的顺序是A到B,这样A节点和B节点就形成了死循环。

简而言之,扩容使得链表的方向发生了反转。而T2线程由于处于阻塞状态对这一切都不知情。T2持有的节点的引用还是A,A的next还是B。但是B的next由于扩容的原因反过来指向了A。死循环就发生了。

TODO 成环之后呢?T2节点执行扩容会发生什么?