2012-05-30 3 views
2

En analysant les billes de l'un des environnements de production, je vis un fil en « ATTENTE » état sur un CountDownLatch attendent()Fil bloqué sur CountDownLatch attendre() lorsque le nombre est 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) 

Le verrou était initialisé à 1 et un autre thread a appelé la méthode countDown() sur la même instance du verrou, mais le thread principal reste bloqué sur le verrou. Cela a conduit à JVM être suspendu indéfiniment. Se bloquer même si le compte du verrou atteint zéro semble déraisonnable et je cherche des suggestions pour résoudre ce problème.

Des idées?

Remarque - La version utilisée est jvm comme ci-dessous

java version "1.5.0_15" Java (TM) 2 Runtime Environment, Standard Edition (build 1.5.0_15-b04) Java HotSpot (TM) Client VM (build 1.5.0_15-b04, mode mixte, partage)

Mise à jour - est ci-dessous l'extrait de code du fil dont je parle ci-dessus

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; 
     } 
    } 

} 


} 

Voici ce que je vois dans les journaux

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 

L'instruction enregistreur après latch.await() est jamais imprimé et la décharge de fil indique que le thread principal est bloqué sur le loquet.

+3

Vous * dites * que 'countDown()' a été appelé sur la même instance - mais je serais plus enclin à croire qu'il y a un bug dans votre code et votre diagnostic que dans les bibliothèques JRE. Pouvez-vous produire un programme court mais complet qui démontre le problème? –

+0

Si je pouvais le démontrer, j'aurais pu connaître probablement la cause première :). La raison pour laquelle je dis que countDown() a été appelée est parce que les instructions du logger l'indiquent. Des instructions de journal sont ajoutées après l'appel de countDown() et celles-ci sont visibles dans les journaux. Le vidage de thread indique cependant que le thread principal attend toujours sur le compte de verrou à zéro. –

+0

J'ose dire que 'countDown' est appelé - mais votre journalisation * aussi * indique indiscutablement qu'elle est appelée sur la même instance? –

Répondre

0

J'aurais aimé écrire ceci comme commentaire mais ma réputation ne permet pas encore de commenter, donc je vais offrir ma petite expérience ici.

Je rencontre le même problème. Mon countDownLatch a été accédé à partir de méthodes synchronisées: la suppression de la synchronisation a résolu le problème (alors que bien sûr j'ai dû ajuster le code des méthodes pour faire face à l'absence de synchronisation). Je n'ai aucune idée de comment expliquer ce comportement.

Questions connexes