HashMap导致死循环问题
虽然我推测是链表形成闭环,但 没有去证明过。从网上找了一下: http://blog.csdn.net/autoinspired/archive/2008/07/16/2662290.aspx 里面也有提到:
产生这个死循环的根源在于对一个未保护的共享变量 — 一个”HashMap”数据结构的操作。当在 所有操作的方法上加了”synchronized”后,一切恢复了正常。检查”HashMap”(Java SE 5.0)的源 码,我们发现有潜在的破坏其内部结构最终造成死循环的可能。在下面的代码中,如果我们使得 HashMap中的entries进入循环,那 么”e.next()”永远都不会为null。
不仅get()方法会这样,put()以及其他对外暴露的方法都会有这个风险,这算jvm的bug吗?应该说不是的,这个现象很早以前就报告出来了(详细见: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6423457)。Sun的工程师并不认为这 是bug,而是建议在这样的场景下应用”ConcurrentHashMap”,在构建可扩展的系统时应将这点 纳入规范中。
这篇翻译提到了对HashMap
的误用,但它没有点破HashMap
内部结构在什么样误用情况下怎么被 破坏的;我想要一个有力的场景来弄清楚。再从李鹏的blog来看,用了2个线程来put就模拟出来了,最后堆栈是在 transfer
方法上(该方法是数据扩容时将数据从旧容器转移到新容器)。 仔细分析了一下里面的代码,基本得出了原因,证明了我之前的推测。
假设扩容时的一个场景如下(右边的容器是一个长度 2 倍于当前容器的数组) 单线程情况。
我们分析数据转移的过程,主要是链表的转移
执行过一次后的状态:
最终的结果:
两个线程并发情况下,扩容时可能会创建出 2 个新数组容器
顺利的话,最终转移完可能是这样的结果
但并发情况下,出现死循环的可能场景是什么呢? 还要详细的分析一下代码,下面的代码中重点在 do/while
循环结构中(完成链 表的转移)。
// 扩容操作,从一个数组转移到另一个数组
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next; //假设第一个线程执行到这里
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null); // 可能导致死循环
}
}
}
2 个线程并发情况下, 当线程 1 执行到上面第 9 行时,而线程 2 已经完成了一 轮 do/while 操作,那么它的状态如下图:
(上面的数组时线程 1 的,已经完成了链表数据的转移;下面的是线程 2 的,它 即将开始进行对链表数据的转移,此时它记录 E1 和 E2 的首位已经被线程 1 翻 转了)
后续的步骤如下:
1) 插入 E1 节点,E1 节点的 next 指向新容器索引位置上的值(null 或 entry)
2) 插入 E2 节点,E2 的 next 指向当前索引位置上的引用值 E1
3)因为 next 不为 null,链表继续移动,此时 2 节点之间形成了闭环。造成了 死循环。
上面只是一种情况,造成单线程死循环,双核 cpu 的话占用率是 50%,还有导致 100%的情况,应该也都是链表的闭环所致。
最终,这并不是 HashMap 的问题,是使用场景的不当,在并发情况下选择非线程 安全的容器是没有保障的。
转自:https://blog.csdn.net/zhao9tian/article/details/38976933
HashMap导致死循环问题的更多相关文章
- Java之HashMap在多线程情况下导致死循环的问题
PS:不得不说Java编程思想这本书是真心强大.. 学习内容: 1.HashMap<K,V>在多线程的情况下出现的死循环现象 当初学Java的时候只是知道HashMap<K,V& ...
- HashMap并发导致死循环 CurrentHashMap
为何出现死循环简要说明 HashMap闭环的详细原因 cocurrentHashMap的底层机制 为何出现死循环简要说明 HashMap是非线程安全的,在并发场景中如果不保持足够的同步,就有可能在执行 ...
- Java HashMap的死循环
在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造 成Race Condition,从而导致死循环.这个事情我4 ...
- 图解集合5:不正确地使用HashMap引发死循环及元素丢失
问题引出 前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死 ...
- 多线程下HashMap的死循环问题
多线程下[HashMap]的问题: 1.多线程put操作后,get操作导致死循环.2.多线程put非NULL元素后,get操作得到NULL值.3.多线程put操作,导致元素丢失. 本次主要关注[Has ...
- [转]不正当使用HashMap导致cpu 100%的问题追究
以前项目中遇到类似业务,但使用的是CurrentHashMap,看到这篇文章,转载记录,警示自己. 以下内容转自: 转载自并发编程网 – ifeve.com(http://ifeve.com/hash ...
- Java HashMap并发死循环
在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...
- 【转】Java HashMap的死循环
问题的症状 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问题,所以需要变成多线程的,于是,变成多线程后到了线上,发现 ...
- 疫苗:JAVA HASHMAP的死循环
在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...
随机推荐
- JavaScript中的XMLDOM对象
测试: demo.xml中的内容: js文件内容: window.onload=function(){ //var v=returnXMLDOM(); //v.loadXML('<root> ...
- CDH版hbase-0.98.1单机安装
HBase 的安装有两种方式:单机安装和分布式安装.HBase的单机安装了解即可,大家重点掌握HBase 分布式集群的安装.下面我们分别进行介绍. HBase 单机安装 HBase 需要运行在 Had ...
- Google NewSQL之Spanner
谷歌分布式三宝 BigTable.GFS.MapReduce这传说中的谷歌分布式三驾马车,虽然谷歌没有公开具体实现代码,但却公布了相应论文,对分布式文件系统.大数据挖掘和NoSQL流行起了重大促进作用 ...
- oracle导入expdp、导出impdp数据库用户
仅限oracle服务器上执行:把172.16.251.136:1521/orcl的AMI4_2用户导入到192.168.2.30:1521/orclss中的AMI1用户: 关于导入导出更详细的见文章 ...
- CF 372B Counting Rectangles is Fun [dp+数据维护]
题意,给出一个n行m列的矩阵 里面元素是0或者1 给出q个询问 a,b,c,d 求(a,b)到(c,d)有多少个由0组成的矩形 我们定义 watermark/2/text/aHR0cDovL2Jsb2 ...
- hive1.2伪分布mysql数据库配置具体解释
hadoop2.6伪分布配置:http://blog.csdn.net/gamer_gyt/article/details/46793731 hive1.2 derby元数据库配置:http://b ...
- Hadoop问题记录:Wrong FS: hdfs://hp5-249:9000/, expected: file:///
一般在对文件操作的时候可能出现这个问题,可能是打开文件的时候出错,也可能是对文件夹进行遍历的时候出问题. 出现这样的问题通常是在eclipse中执行hadoop的时候出现,直接切换到shell下发送命 ...
- C4
#include <stdio.h> int main(int argc, const char * argv[]) { // int 占用4个字节 double 占用8个字节 // 只是 ...
- Caffe C++API 提取任意一张图片的特征系列二----MemoryData
介绍一种更加灵活的方法,用MemoryData层输入数据,可以直接用opencv接口读入我们的图片再添加的网络中. 第一个问题:仍然是工程建立问题,提示卷积层或其他层没有注册,解决方法与上一篇博客一 ...
- 在单机上安装多个oracle实例
1 在 hp unix上安装 oracle 10g ,这个不解释,直接安装好. 创建组oinstall,dba,用户oracle [root@node1 ~]# groupadd oinstal ...