HashMap 将 cpu 打满始末
什么情况下使用HashMap会导致cpu被打满呢?
一般来说cpu被打满,我们会有一个下意识的想法是程序出现了死循环,那死循环是怎么产生的呢?这种情况很诡异,正常的单线程情况下不会出现,所以,以造成诡异bug著称的多线程就得出来背锅了。
事实上,该问题的确是在多线程中不恰当使用HashMap导致的,因为HashMap不是线程安全的。
下面通过举例分析多线程情况下,死循环的产生过程:
1、首先,该过程发生在HashMap进行容量扩容的过程,核心代码如下:
正常情况下(无线程竞争)的扩容过程:
1)假设size=2的一个HashMap,准备扩容到size=4.
2)遍历数组中的每条链表,将元素插入到新数组的链表中,直至next=null:
多线程不同步情况下会产生死循环的场景:
1)我们假设有T1和T2。两个线程同时调用扩容过程,也即上面那段代码。当T1执行完第9行,线程被切换:
此时的HashMap的指针情况:e和next被设置指向如下(在e和next后面加1,代表T1线程):
2)紧接着,T2开始执行,并执行完整个扩容过程:
3)重点:此时T2将B指向了A,e1指向A,next1指向B。当T1恢复执行时,会将A的next指向B,循环指向产生。完整的执行过程如下:
以上就是HashMap将cpu打满的全过程,是线程安全的典型案例。解决方法很简单,就是做好同步。
参考资料:
版权声明: 本文为 InfoQ 作者【林昱榕】的原创文章。
原文链接:【http://xie.infoq.cn/article/bb568195178db540180ac5ffa】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论