HashMap为什么线程不安全?浅析高并发情况下的HashMap
来源:互联网 发布:mac版cad2016汉化包 编辑:程序博客网 时间:2024/06/05 01:37
在了解hashmap为什么不是线程安全的之前,要先了解hashmap的扩容机制,之前已做过分析(传送门在此)
知道了hashmap的扩容机制,就正式说一下多线程环境中,hashmap会有什么样的问题(问题主要出在扩容时的ReHash操作),
假设:此时一个HashMap已经到达了临界点,需要进行扩容( ReSize() )的动作。这时又两个线程 A和B,同时要对这个HashMap进行了put操作:
put动作执行完毕之后变成:
超过临界值,线程A和B各自进行ReSize()的操作,分别对hashmap进行了扩容。
注意此时还没有进行Rehash的过程,只是创建了一个长度是原hashMap数组的2倍新的Entry空数组:
好,接下来线程A和B就要进行ReHash的动作了,回顾一下Rehash的源码:
再一次假设:
1、线程A畅通无阻的进行着ReHash
2、线程B遍历到了Entry3对象,执行完上面红框中的代码之后,线程被挂起了。此时在B的眼里:e = Entry3,next = Entry2;
此时的状态如下(e和next代表线程B的引用):
接下来线程B开始执行他的ReHash操作(对于此时的B,***e = Entry3
next = Entry2***):
执行到上面红框这句时,刚刚假设了A对于Entry3的hash结果是3,所以B的hash结果也肯定是3,所以i=3。
继续执行,Entry3放入了线程B中数组下标为3的位置,且e指向了Entry2。此时:e = Entry2 ,next = Entry2
此时的状态:
然后再一次执行transfer代码:
此时:e = Entry2,next = Entry3;
整体状态如下:
然后从红框位置继续执行代码,用头插法把Entry2插入到了线程B的数组的头结点,执行完毕之后的状态为:
接下来又进行了一次循环,执行了transfer代码:
又执行到这句时:e = Entry3 , next = Entry3.next = null;
接下来执行这句时:
重点!桥黑板划重点了!!
newTable[i] = Entry2
e = Entry3
Entry2.next = Entry3
Entry3.next = Entry2
!!!!!!!!!!!链表出现了闭环!!!!!!
整体状态变成了下图:
当调用Get方法查找一个不存在的Key,而这个Key的Hash结果恰好等于3的时候,由于位置3带有环形链表,所以程序将会进入死循环!
正因为形成了闭环,会导致程序进入死循环,所以才说hashmap是线程不安全的。
总结:
在多线程情况下,会导致hashmap出现链表闭环,一旦进入了闭环get数据,程序就会进入死循环,所以导致HashMap是非线程安全的。
致谢:小灰
- HashMap为什么线程不安全?浅析高并发情况下的HashMap
- hashmap为什么线程不安全
- HashMap为什么线程不安全
- HashMap为什么线程不安全
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的?
- 为什么HashMap是线程不安全的
- HashMap为什么是线程不安全的?
- HashMap为什么是线程不安全的
- 虚拟机安装和虚拟机环境下安装Linux操作系统
- 结构体和数组
- 关于JSON最实用的代码(一)
- DSS 代码分析【SR包发送】
- Filebeat中文指南
- HashMap为什么线程不安全?浅析高并发情况下的HashMap
- Retrofit源码解析
- Netty源码分析(三)—数据管道ChannelPipeline源码分析
- jsoup通过获取的内容写自己的页面
- shell启动程序的四种方式
- centos 6.8 安装jdk
- bootstrap滑动按钮/取值
- CNN结构:色彩特征提取-色彩属性HSV空间(色彩冷暖初始)
- [BZOJ3110][Zjoi2013]-K大数查询-树套树