Your SlideShare is downloading. ×
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Hash map导致cpu100% 的分析

1,129

Published on

java Hashmap cpu 100%

java Hashmap cpu 100%

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,129
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.李鹏同学在blog里写了篇关于HashMap死锁模拟的文章:http://blog.csdn.net/madding/archive/2010/08/25/5838477.aspx做个纠正,那个不是死锁问题,而是死循环。这个问题,我们以前讨论过。校长之前的blog:http://sdh5724.javaeye.com/blog/619130和淘宝的毕玄的《分布式Java应用:基础与实践》一书中都提到过 velocity导致cpu 100%的bug,起因是HashMap的使用不当所致。在之前的邮件列表里,校长提出过这个问题,当时我没仔细看,不清楚这个问题究竟是对HashMap的误用,还是HashMap的潜在问题,当时感觉不太可能是HashMap自身的问题,否则问题大了。应该是属于在并发的场景下错误的使用了HashMap。昨天看了李鹏的blog后,觉得这个事情还是应该搞清楚一下;虽然我推测是链表形成闭环,但没有去证明过。从网上找了一下: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. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. E1 E2我们分析数据转移的过程,主要是链表的转移。 Nul null or X X E1 X E2 X e next执行过一次后的状态:
  • 3. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul Null E1 E2 e最终的结果: Nul Null/E E1 E2两个线程并发情况下,扩容时可能会创建出 2 个新数组容器。
  • 4. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul null or X X E1 X E2 e next null or X顺利的话,最终转移完可能是这样的结果
  • 5. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul Null/ E1 E2但并发情况下,出现死循环的可能场景是什么呢?还要详细的分析一下代码,下面的代码中重点在 do/while 循环结构中(完成链表的转移)。// 扩容操作,从一个数组转移到另一个数组1 void transfer(Entry[] newTable) {2 Entry[] src = table;3 int newCapacity = newTable.length;4 for (int j = 0; j < src.length; j++) {5 Entry<K,V> e = src[j];6 if (e != null) {7 src[j] = null;8 do {9 Entry<K,V> next = e.next; //假设第一个线程执行到这里10 int i = indexFor(e.hash, newCapacity);11 e.next = newTable[i];12 newTable[i] = e;
  • 6. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.13 e = next;14 } while (e != null); // 可能导致死循环15 }16 }17 }2 个线程并发情况下, 当线程 1 执行到上面第 9 行时,而线程 2 已经完成了一轮 do/while 操作,那么它的状态如下图:(上面的数组时线程 1 的,已经完成了链表数据的转移;下面的是线程 2 的,它即将开始进行对链表数据的转移,此时它记录 E1 和 E2 的首位已经被线程 1 翻转了) Nul Null/ E1 E2 e next后续的步骤如下:1) 插入 E1 节点,E1 节点的 next 指向新容器索引位置上的值(null 或 entry)
  • 7. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul Null/ E1 E2 e next2) 插入 E2 节点,E2 的 next 指向当前索引位置上的引用值 E1
  • 8. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul Null/ E1 E2 e next3)因为 next 不为 null,链表继续移动,此时 2 节点之间形成了闭环。造成了死循环。
  • 9. Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Nul Null/ E1 E2 e上面只是一种情况,造成单线程死循环,双核 cpu 的话占用率是 50%,还有导致100%的情况,应该也都是链表的闭环所致。最终,这并不是 HashMap 的问题,是使用场景的不当,在并发情况下选择非线程安全的容器是没有保障的。

×