HashMap多线程死循环问题

× 文章目录
  1. 一.HashMap出现死循环原因
    1. 1.1 什么是线程安全
    2. 1.2 为何出现死循环简要说明
  2. 二.HashMap死循环原因分析
    1. 2.1 问题的症状
    2. 2.2 为什么会造成死循环
  3. 三.参考文章

摘要:一直都知道Java HashMap使用不当会导致CPU 达到100%的线上故障,以及怎么造成的,怎么在使用过程中进行规避,由于时间的关系。最近整理如本文所示。

一.HashMap出现死循环原因

1.1 什么是线程安全

多个线程访问某一个类(对象和方法)时,这个类的对象或方法都能始终表现出正确的行为或者我们想要的结果,我们就认为其是线程安全的,否则非线程安全。我们都知道HashMap是非线程安全的,那怎么使用HashMap会导致CPU占用率达到100%。

之所以会导致HashMap出现死循环是因为多线程会导致HashMap的Entry节点形成环链,这样当遍历集合时Entry的next节点由于不为空,从而形成死循环,从而导致CPU达到100%

1.2 为何出现死循环简要说明

HashMap是非线程安全的,在高并发场景下,如果不能保持足够的同步,就有可能在执行HashMap.get时进入死循环,将CPU的消耗到100%。

  • HashMap采用链表解决Hash冲突。因为是链表结构,那么就很容易形成闭合的链路,这样在循环的时候只要有线程对这个HashMap进行get操作就会产生死循环,

  • 单线程情况下,只有一个线程对HashMap的数据结构进行操作,是不可能产生闭合的回路的。

  • 只有在多线程并发的情况下才会出现这种情况,那就是在put操作的时候,如果size>initialCapacity*loadFactor,hash表进行扩容,那么这时候HashMap就会进行rehash操作,随之HashMap的结构就会很大的变化。很有可能就是在两个线程在这个时候同时触发了rehash操作,产生了闭合的回路。

二.HashMap死循环原因分析

2.1 问题的症状

在多线程下使用HashMap,到了线上之后,我们发现程序经常占了100%的CPU,查看堆栈,你会发现程序都Hang在了HashMap.get()这个方法上了,重启程序后问题消失。但是过段时间又会来。而且,这个问题在测试环境里可能很难重现。

2.2 为什么会造成死循环

HashMap采用链表解决Hash冲突,因为是链表结构,那么就很容易形成闭合的链路,这样在循环的时候只要有线程对这个HashMap进行get操作就会产生死循环。但是,我好奇的是,这种闭合的链路是如何形成的呢。在单线程情况下,只有一个线程对HashMap的数据结构进行操作,是不可能产生闭合的回路的。那就只有在多线程并发的情况下才会出现这种情况,那就是在put操作的时候,如果size>initialCapacity*loadFactor,那么这时候HashMap就会进行rehash操作,随之HashMap的结构就会发生翻天覆地的变化。很有可能就是在两个线程在这个时候同时触发了rehash操作,产生了闭合的回路。

三.参考文章

http://blog.csdn.net/xuefeng0707/article/details/40797085

http://coolshell.cn/articles/9606.html

http://firezhfox.iteye.com/blog/2241043

http://www.cnblogs.com/kxdblog/p/4323892.html

http://www.cnblogs.com/ITtangtang/p/3966467.html

http://blog.csdn.net/xuefeng0707/article/details/40797085
http://blog.csdn.net/zhuqiuhui/article/details/51849692

如果您觉得文章不错,可以打赏我喝一杯咖啡!