| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> HashMap为什么会发生死循环 -> 正文阅读 |
|
[数据结构与算法]HashMap为什么会发生死循环 |
HashMap死循环只会在JDK1.7中出现,出现的原因主要是因为其自身扩容机制加上并发操作。JDK1.8中已彻底解决该问题。源码可参考:为什么HashMap并发时会引起死循环?_光阴似键的博客-CSDN博客_hashmap为什么会造成死循环 JDK1.7中HashMap以数组加链表的方式存储,在插入数据是采用的是头插法,新插入的数据会从链表的头结点进行插入。因此在HashMap扩容时会存在如下现象: 死循环演示1. 线程 T1 和线程 T2 要对 HashMap 进行扩容操作,此时 T1 和 T2 指向的是链表的头结点元素 A,而 T1 和 T2 的下一个节点,也就是 T1.next 和 T2.next 指向的是 B 节点,如下图所示: 2.线程 T2 时间片用完进入休眠状态,而线程 T1 开始执行扩容操作,一直到线程 T1 扩容完成后,线程 T2 才被唤醒,扩容之后的场景如下图所示,可见扩容完成后,T2仍指向A,T.next仍指向B。 3.当线程 T1 执行完,而线程 T2 恢复执行时,死循环就建立了,如下图所示: ?线程T1先执行完扩容后,线程T2的指向没有改变,T1 执行完之后的顺序是 B 到 A,而 T2 的顺序是 A 到 B,这样 A 节点和 B 节点就形成死循环了。 解决方案1)使用线程安全的容器ConcurrentHashMap替代HashMap(推荐,面试可能会引出oncurrentHashMap底层是如何实现线程安全的,jdk7跟8有什么别去,再说说分段锁有什么优缺点)? 2)使用线程安全的容器Hashtable替代(性能低,不建议,可能会引出为什么性能低) 3)使用 synchronized 或 Lock 加锁 HashMap 之后,再进行操作,相当于多线程排队执行(比较麻烦,也不建议使用) 总结HashMap 死循环发生在 JDK 1.7 版本中 主要原因:?头插法 + 链表 + 多线程并发 + 扩容,累加到一起形成了 HashMap 的死循环 解决方案:多线程下建议使用?ConcurrentHashMap 替代 JDK1.8中,HashMap改成了尾插法,解决了链表死循环问题 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 19:44:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |