【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
📚回答:
背景知识:
在JDK1.7中,HashMap在处理哈希冲突时,链表采用的是头插法。也就是说,当发生扩容时,链表中的节点会以头插入的方式重新排列到新的数组中。这种设计在多线程环境下会导致死循环问题。死循环的原因:
- 假设
HashMap中有三个节点A -> B -> C,其中A是头节点,C是尾节点。 - 当扩容时,如果有两个线程(
T1和T2)同时操作:T1先完成迁移,将链表重新排列为C -> B -> A(头插法导致顺序反转)。T2在迁移时,由于它记录的状态是旧链表的顺序(A -> B -> C),而此时新链表已经是C -> B -> A。- 这会导致
T2尝试插入节点时,出现环形链表(如A指向B,B又指向A),从而引发死循环。
- 假设
解决方案:
- JDK1.8中将链表的插入方式改为尾插法,避免了扩容时链表顺序反转的问题,从而解决了死循环问题。
- 如果需要在多线程环境下使用
HashMap,建议改用线程安全的ConcurrentHashMap。
💡面试官视角:
- 面试官可能会问“为什么头插法会导致死循环?”答:因为头插法在扩容时会反转链表顺序,多个线程同时操作时可能形成环形链表,导致死循环。
- 面试官可能会追问“为什么JDK1.8改用尾插法就能解决问题?”答:尾插法在扩容时不会改变链表顺序,因此避免了环形链表的形成。
📌专栏:大白话说Java面试题 — 01-Java基础篇
