当count为0时,在CountDownLatch await()上阻塞线程

时间:2012-05-30 05:42:10

标签: java countdownlatch

在分析其中一个生产环境的日志时,我在countdownlatch上看到一个处于“W​​AITING”状态的线程await()

...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) Java HotSpot(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;
        }
    }

}


}

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

以下是我在日志中看到的内容

从不打印latch.await()之后的logger语句,并且线程转储也表明主线程在锁存器上被阻塞。

1 个答案:

答案 0 :(得分:1)

我本来想把它写成评论,但我的声誉还不允许评论,所以我会在这里提供我的小经验。

我遇到了同样的问题。我的countDownLatch是从同步方法访问的:删除同步解决了问题(当然我必须调整方法的代码以应对没有同步)。我不知道如何解释这种行为。