Analyzing the Dead Loop Issue in JDK 1.7 HashMap and Its Resolution in JDK 1.8
This article explains why the pre‑JDK 1.8 HashMap can enter an infinite loop during concurrent resizing, illustrates the problem with detailed step‑by‑step diagrams, and shows how JDK 1.8 redesigns the resize algorithm to prevent the loop.
In the previous article we dissected memory‑leak issues of LinkedHashMap under multithreaded read‑write locks; here we continue the deep‑dive style, now focusing on a classic concurrency problem: why HashMap before JDK 1.8 can dead‑loop under multithreading.
Part 1 – Overview of JDK 1.7 HashMap
HashMap stores entries using an array of buckets combined with linked lists to resolve hash collisions. As the number of elements grows, the map expands its internal array (ignoring load‑factor details here). After expansion, each entry must be re‑hashed and moved to the appropriate bucket in the new array.
The expansion works by allocating a new array, then re‑inserting each original entry into the new array using head‑insertion, finally replacing the old array with the new one.
The question is: why does this process cause an infinite‑loop (cycle) when performed concurrently?
Part 2 – Analyzing the Cause of the Cycle
A single animated diagram (see the GIF) illustrates the scenario.
Assume three entries <18,A>, <48,B>, <86,C> are stored in table[3] as a linked list.
Thread 1 is pre‑empted after reading the first entry (e = <18,A>, next = <48,B>). When it resumes, Thread 2 has already completed the resize, so newTable[19] now points to the list <86,C> → <48,B> → <18,A> (tail‑insertion order).
If Thread 1 continues processing the original order and inserts each element at the head of the new list, the resulting order becomes <48,B> → <18,A> → <86,C> → <48,B> → <18,A>, creating a cycle where <18,A>.next points back to <86,C> instead of null .
Consequently, a call to get(19) may traverse the list forever because the linked list has become a loop.
Part 3 – Why JDK 1.8 Does Not Form a Cycle
The JDK 1.8 resize implementation (see the screenshot) fixes the issue in two ways:
It uses tail‑insertion, preserving the original order of the linked list in the new table.
It employs a local variable to hold the element being moved and only assigns it to the new table after the move, avoiding in‑place modifications that could create a cycle.
Part 4 – Conclusion
Regardless of the version, HashMap is not thread‑safe; developers must take special precautions when using it in concurrent environments.
If you find any issues with the analysis, feel free to add me on WeChat for further discussion.
When you dig into the code line by line and uncover the root cause, there’s a unique sense of satisfaction.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.