历史背景
HashMap的死循环只是在JDK1.7中会出现。主要是HashMap自身的工作机制,再加上并发操作,从而会导致死循环的出现。
在JDK1.8以后,官方彻底地解决了这个问题。
数据插入原理
JDK1.7中HashMap插入数据的原理:
底层的数据存储结构:数据+链表
插入数据的方式:头插法
导致死循环的原因
还原并发场景下HashMap扩容导致的死循环问题:
- 线程启动
- 开始扩容
假设线程T2的时间片用完,进入休眠状态。线程T1开始执行扩容动作。一直到线程T1扩容完之后,线程T2才被唤醒。线程T1完成扩容之后的场景如下图:
当线程T1执行完成之后,线程T2恢复执行,死循环这时候就发生了:
A节点和B节点就形成了死循环。
解决方案
- 使用线程安全的ConcurrentHashMap来替代HashMap,推荐。
- 使用线程安全的Hashtable替代,性能低,不建议。
- 使用synchronized或Lock加锁,会影响性能,不建议。(相当于多线程排队执行)