jdk1.7中,resize方法在并发时,有可能将链表变成环,导致程序无止境的循环下去。
导致这种bug的产生原因是,扩容过程采用头插法,会导致链表方向逆向,从而有可以成环
jdk1.8修改了1.7中的倒插法,链表的元素扩容之后,只可能分配到两个地方,1.当前所在的哈希表的下标处,2.当前所在的哈希表的下标处+当前哈希表的容量。
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
通过(e.hash & oldCap) == 0 判断,然后依次修改链表元素的next,形成两条链表,这个区别于1.7,不会形成链表方向的改变。
JDK1.8链表扩容优化:避免并发时的环形bug
本文探讨了JDK1.7中resize方法的并发问题,解释了1.8如何通过改进策略防止链表成环。重点在于1.8的扩容方法避免了方向反转,确保了线程安全。
1万+

被折叠的 条评论
为什么被折叠?



