大家不用關心程序實際邏輯是否正確,只是好奇,為什么這個程序會hang住不運行了?而且CPU會占用100%

          import java.util.HashMap;

          public class TestLock {

          private HashMap map = new HashMap();

          public TestLock() {
          Thread t1 
          = new Thread() {
          public void run() {
          for(int i=0; i<50000; i++) {
          map.put(
          new Integer(i), i);
          }
          System.out.println(
          "t1 over");
          }
          };

          Thread t2 
          = new Thread() {
          public void run() {
          for(int i=0; i<50000; i++) {
          map.put(
          new Integer(i), i);
          }

          System.out.println(
          "t2 over");
          }
          };


          t1.start();
          t2.start();

          }


          public static void main(String[] args) {    
          new TestLock();
          }
          }


          Dump thread會看到,程序hang到:

          "Thread-1" prio=6 tid=0x00c70bd8 nid=0x914 runnable [0x02ebf000..0x02ebfc68]
          at java.util.HashMap.put(HashMap.java:420)
          at TestLock$2.run(TestLock.java:20)

          "Thread-0" prio=6 tid=0x00c70a50 nid=0x578 runnable [0x02e7f000..0x02e7fb68]
          at java.util.HashMap.put(HashMap.java:420)
          at TestLock$1.run(TestLock.java:11)

          Feedback

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 17:53 by nobody
          HashMap 不是線程安全的;請換成Hashtable。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 18:23 by Scud(飛云小俠)
          我在本地運行了一下 沒發現死鎖.

          你可以用visualvm 檢測一下, 它可以發現是否死鎖, 已經死鎖的行數等信息

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 20:07 by stone2083
          "Thread-1" prio=6 tid=0x00c70bd8 nid=0x914 runnable
          兩個線程都是runnable狀態.

          這程序,理論上,不應該出現死鎖的.

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?[未登錄]  回復  更多評論   

          2010-08-04 20:39 by 行云流水
          不會發生死鎖。不是線程安全的hashmap,貌似你也沒有用到鎖的概念。只是到最后map里面的數據大于50000.

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 21:02 by 天快黑了
          @nobody
          這個知道,現在是想搞明白程序為什么會hang在那不走了

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 21:03 by 天快黑了
          @Scud(飛云小俠)
          應該是與機器有關,我公司機器,使用300個循環就會hang,你可以試著把循環調大一點試試看。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 21:30 by stone2083
          突然記起來了.請參考這篇文章:
          http://sdh5724.javaeye.com/blog/619130

          在自己電腦上,一直無法重現這個問題(無論加大循環,或者增加線程數),明天回公司再去看看.

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-04 22:02 by 天快黑了
          @stone2083
          非常感謝提供的鏈接。

          對,可能是多個線程同時修改HashMap,導致,HashMap內部死循環了。不過奇怪,不管怎么dump thread,都是hang在HashMap.java:420,而查看HashMap的代碼,怎么也想不通這個地方會hang住。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 09:37 by peacess
          線程還在運行,而main函數已經退了,

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 10:50 by 豬兒笨笨
          你在put方法420行的循環中 加一句
          System.out.println(e+" "+e.next);

          就會產生一個死循環,即e=e.next.next。
          應該是多線程下,進行hash處理的時候出現的。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 12:31 by 天快黑了
          @豬兒笨笨
          e.next訪問的是e的一個屬性,怎么會相當于e.next.next?

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 19:06 by bigwesthorse
          我改成了concurrenthashmap還是會出現,只是出現的頻率降低了不少,大家可以陸續開上千個進程試一下
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          start javaw TestLock
          ...........etc

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 19:13 by bigwesthorse
          @bigwesthorse
          只有hashtable可以順利地通過1429個進程測試,哈哈,似乎看到了一點讓人驚喜的東西

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?[未登錄]  回復  更多評論   

          2010-08-05 20:58 by kafka0102
          死循環的代碼在hashmap的transfer方法:
          void transfer(final Entry[] newTable) {
          final Entry[] src = table;
          final int newCapacity = newTable.length;
          final long time1 = System.currentTimeMillis();
          for (int j = 0; j < src.length; j++) {
          Entry<K,V> e = src[j];
          if (e != null) {
          src[j] = null;
          do {
          final Entry<K,V> next = e.next;
          final int i = indexFor(e.hash, newCapacity);
          e.next = newTable[i];
          newTable[i] = e;
          e = next;
          } while (e != null);
          }
          }
          }
          我的分析是:死循環就在while中,對同一個舊table中的e,一個線程執行了 e.next = newTable[i];(還沒到 e = next;),另一個才到 final Entry<K,V> next = e.next;,結果后到的線程接著執行e = next;造成e=e.next,死循環了。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 22:00 by 豬兒笨笨
          樓上的
          不是e=e.next
          而是e=e.next.next
          不過你的分析應該是對的,就是在根據hashcode計算位置的時候,因為并發的原因出現問題了。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 22:01 by 豬兒笨笨
          @天快黑了

          這個很正常的,因為e.next相當于一個鏈表指針,指向下一個點,它們是同一個例的實類。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 22:03 by 豬兒笨笨
          另外,關于HashMap的實現,已經說了是線程不安全的,多線程下,出現問題是正常的。

          Hashtable一直線程安全,可以放心用。
          但說concurrenthashmap不對,這個應該不會。
          回頭也試一下再來討論。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-05 22:38 by 豬兒笨笨
          用了concurrenthashmap,循環5000次,沒有出現問題。

          public TestLock() {


          for (int i = 0; i < 5000; i++) {

          final int count=i;

          Thread t1 = new Thread() {
          public void run() {
          for (int i = 0; i < 50000; i++) {
          map.put(new Integer(i), i);

          }
          System.out.println(count+" over");
          }
          };

          t1.start();
          }
          }

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-06 09:27 by bigwesthorse
          @豬兒笨笨
          對于concurrenthashmap
          用一個批處理寫1000多個start javaw TestLock
          肯定會出現的,我說了概率很低,基本上兩三百個程序會有個卡死
          你就等著那個批處理狂跑就行了,1到2分鐘之后,你就會感到cpu100%了
          被某個進程霸占了,一直hang在那里

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-06 15:36 by 豬兒笨笨
          沒有明白樓上說什么意思?
          這樣說吧,是否在一個JVM內,還是說同時啟動多個JVM?
          如果多個JVM,就很難說有什么問題,比如說用光了資源,等等。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-06 16:16 by bigwesthorse
          @豬兒笨笨
          就是這個程序是否出現死鎖要看rp的,跑個200多次才會出現一次
          我用批處理連續跑了上千次,出現了好幾次死鎖的情況

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?  回復  更多評論   

          2010-08-07 10:51 by 天快黑了
          感謝大家的回復,這個問題確實很難解釋清楚。我們只能注意,多線程下千萬不要使用非線程安全的對象。

          # re: 誰能幫忙解釋一下為什么這個程序會死鎖?[未登錄]  回復  更多評論   

          2010-10-20 16:59 by littleJava
          @豬兒笨笨
          ConcurrentHashMap只是保證Happens-before關系,勉強的線程安全,如果需要保證數據一致性,還是用Collections.synchronizedMap(Map map)方法,利用的synchronized機制,規劃好代碼流程來實現線程安全

          posts - 5, comments - 25, trackbacks - 0, articles - 1

          Copyright © 天快黑了

          主站蜘蛛池模板: 舞钢市| 昔阳县| 贵港市| 桐梓县| 武汉市| 湾仔区| 刚察县| 伽师县| 中宁县| 惠水县| 漯河市| 永修县| 汾西县| 壶关县| 谢通门县| 子洲县| 台山市| 辽中县| 元阳县| 铜鼓县| 潼关县| 安陆市| 阿坝| 长泰县| 长沙市| 富蕴县| 乡宁县| 全椒县| 永川市| 平山县| 乌海市| 珲春市| 九江市| 夏邑县| 河南省| 宁阳县| 寿宁县| 扬州市| 克拉玛依市| 延吉市| 柯坪县|