2012-05-30 44 views
2

在分析所述生產環境中的一個的日誌,我看到一個線程在「等待」狀態上的CountDownLatch等待()線程阻塞CountDownLatch等待()時計數爲0

...sun.misc.Unsafe.park(Native Method) 
...java.util.concurrent.locks.LockSupport.park(Unknown Source) 
...java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source) 
...java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source) 
...java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source) 
...java.util.concurrent.CountDownLatch.await(Unknown Source) 

閂鎖是初始化爲1,另一個線程在鎖存器的同一個實例上調用了countDown()方法,但主線程仍然鎖定在鎖存器上。這導致jvm被無限期地掛起。

即使鎖存計數達到零也會被阻塞聽起來不合理,我正在尋找進一步解決此問題的建議。

任何想法?

注 - 使用的JVM版本如下

Java版本 「1.5.0_15」 的Java(TM)2運行環境,標準版(建立1.5.0_15-B04) 的HotSpot的Java(TM)客戶端VM(建立1.5.0_15-B04,混合模式,共享)

更新 - 下面是我說的線程的代碼段中

private class MyRunnable implements Runnable, Thread.UncaughtExceptionHandler { 

     private AtomicBoolean shouldStop = new AtomicBoolean(false); 
     private CountDownLatch stopLatch = new CountDownLatch(1); 
     private Thread currentThread; 

    public void run() { 

     Thread.currentThread().setName("My Thread"); 
      Thread.currentThread().setUncaughtExceptionHandler(this); 
      currentThread = Thread.currentThread(); 
      if (currentThread.isInterrupted()) { 
       logger.debug("The pool thread had its interrupted stattus set. Clearing..."); 
       Thread.interrupted(); 
       logger.debug("The pool thread had its interrupted stattus set. Clearing...DONE"); 
      } 
      try { 
       doBusinessLogic(shouldStop); 
      } catch (Exception e) { 
       logger.error("An exception was encountered in the thread", e); 
      } finally { 
       if (currentThread.isInterrupted()) { 
        logger.debug("Clearing interupted status for the thread and returning to pool..."); 
        Thread.interrupted(); 
       } 
       stopLatch.countDown(); 
       logger.debug("Stopped task after counting down on the latch"); 
      } 
     } 

     public void stopThread() { 
      shouldStop.set(true); 
      logger.debug("Stop flag was set to true.. waiting for thread method to return..."); 
      try { 
       stopLatch.await(); 
       logger.debug("Stop flag was set to true... task has finished. Returning."); 
      } catch (InterruptedException e) { 
       logger.error("Interrupted while awaiting thread stop event...", e); 
      } 
     } 

     public void uncaughtException(Thread t, Throwable e) { 
      logger.error("An uncaught exception occurred in the task thread ", e); 
     } 


     private void doBusinessLogic(AtomicBoolean shouldStop) { 
    long sleepPeriod = 11; 
    while (!shouldStop.get()) { 
     try { 
      Thread.sleep(sleepPeriod); 
     } catch (InterruptedException e) { 
      logger.debug("Thread was interrupted.Clearing interrupted status and proceeding", e); 
      if (Thread.currentThread().isInterrupted()) 
       Thread.interrupted(); 
     } 
     if (shouldStop.get()) { 
      logger.debug("Stop flag was set. Returning."); 
      return; 
     } 
     try { 
      logger.debug("Performing business logic..."); 
      //..... 
      logger.debug("Performing business logic...DONE"); 
     } catch (Throwable e) { 
      logger.error("An exception occurred", e); 
     } 
     if (shouldStop.get()) { 
      logger.debug("Stop flag was set. Returning."); 
      return; 
     } 
    } 

} 


} 

這是我在看日誌

DEBUG [main Thread] - Stop flag was set to true.. waiting for thread method to return... 
DEBUG [My Thread] - Stop flag was set. Returning. 
DEBUG [My Thread] - Stopped task after counting down on the latch 

記錄器語句後latch.await()是從來沒有打印,並且線程轉儲也表示主線程被阻塞上的閂鎖。

+3

你*說*在同一個實例上調用了'countDown()',但我更傾向於認爲代碼和診斷中存在一個錯誤,而不是JRE庫中的錯誤。你能製作一個簡短但完整的程序來證明這個問題嗎? –

+0

如果我可以證明它,我可能已經知道可能已知的根本原因:)。我說countDown()被調用的原因是因爲記錄器語句表明它。在調用countDown()之後添加了日誌語句,這些日誌語句在日誌中顯示。雖然線程轉儲表明主線程仍然等待鎖存計數爲零。 –

+0

我敢說'countDown'被稱爲 - 但是你的日誌記錄*還*無可爭議地表明它被稱爲同一個實例嗎? –

回答

0

我本來想寫這個作爲評論,但我的名聲不允許評論,所以我會在這裏提供我的小經驗。

我遇到了同樣的問題。我的countDownLatch是從同步方法訪問的:刪除同步解決了問題(當然,我不得不調整方法的代碼來應對沒有同步)。我不知道如何解釋這種行爲。