首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是否是对初始计数=1的CountdownLatch的不当使用?

这是否是对初始计数=1的CountdownLatch的不当使用?
EN

Stack Overflow用户
提问于 2013-12-27 07:59:23
回答 3查看 1.5K关注 0票数 1

下面是由Brain编写的“java并发实践”一书中的清单5.11。

我发现下面的代码令人费解。倒计时锁存的'startGate‘似乎有一个错误的用法。(“endGate”的用法没有问题)

代码语言:javascript
复制
public class TestHarness {
public long timeTasks(int nThreads, final Runnable task)
        throws InterruptedException {
    final CountDownLatch startGate = new CountDownLatch(1);
    final CountDownLatch endGate = new CountDownLatch(nThreads);
    for (int i = 0; i < nThreads; i++) {
        Thread t = new Thread() {
            public void run() {
                try {
                    startGate.await();
                    try {
                        task.run();
                    } finally {
                        endGate.countDown();
                    }
                } catch (InterruptedException ignored) {
                }
            }
        };
        t.start();
    }
    long start = System.nanoTime();
    startGate.countDown();
    endGate.await();
    long end = System.nanoTime();
    return end - start;
}

}

startGate.countDown()的执行将通知等待锁存的所有工作线程。但是这能保证通知所有的nThreads吗?

很可能只有几个线程(比如2个线程)执行了run()方法的startGate.await()调用。

此时,主线程执行startGate.countDown()。此调用将只通知等待锁存的2个线程(退出nThreads )。

现在,其他线程( nThread - 2)稍后将调用startGate.await(),但由于主线程已经发出通知,所以工作线程(nThread-2)现在将无限期地等待通知?

还是我漏掉了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-27 08:04:20

一旦startGate.countDown();被调用,计数是零(因为它从1开始)。后来打给startGate.await();的电话..。别等了,已经算成零了。

来自CountDownLatch.await()

如果当前计数为零,则此方法将立即返回。

CountDownLatch只用于阻塞线程,直到另一个线程中的某些工作完成为止。工作完成后,锁存器被计数为零,允许任何等待线程或未来线程继续通过它。

票数 3
EN

Stack Overflow用户

发布于 2013-12-27 08:13:00

CountDownLatch countDown()不是一个可以忽略的通知,而是一个Gate。因此,一旦大门打开,它在任何时候都是开放的。因此,调用await()的其他线程将直接被允许,而不阻塞

票数 1
EN

Stack Overflow用户

发布于 2013-12-27 10:02:38

感谢“大脑”和“纳伦德拉”的回答。刚刚看过了CountDownLatch和AbstractQueuedSynchroniser类的源代码之后,我想添加一些更多的细节。

这不是一个基于wait()notify()的系统,我错误地认为这是因为CountdownLatch.await()方法。

  • CountdownLatch.countDown():如果当前计数等于0,那么它什么也不做,只返回。否则,它首先将计数减少1,然后检查它是否为0。如果为0,则释放“共享”。
  • CountdownLatch.await():检查当前计数,如果它等于0(可能在两者之间被中断),那么它什么也不做,只返回。只有在计数>0(或未被中断)时,此方法才能获得“共享”。

看起来像latch = new CountDownLatch(0)这样的声明虽然无害,但却是一个毫无价值的声明,应该在构造函数代码中引发异常,就像它对count < 0所做的那样。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20797051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档