条件实例signalAll()不返回 [英] Condition instance signalAll() doesn't return

查看:96
本文介绍了条件实例signalAll()不返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

@Log4j
public class ItemStore {
    final Lock lock = new ReentrantLock();
    final Condition hasItem = lock.newCondition();

    private Map<String, String> store = new Hashtable<>();

    public void put( String handle, String item) {
        store.put( handle, item );
        log.info("stored " + handle );
        hasItem.signalAll();
        log.info("signaled all threads");
    }

    public String fetchWithTimeout( String handle, long timeoutInSec ) throws InterruptedException {
        try {
            lock.lock();
            while ( !store.containsKey( handle ) ) {
                log.info("store doesn't have " + handle + "; keep waiting");
                hasItem.await( timeoutInSec, TimeUnit.SECONDS);
            }
            return store.get( handle );
        } finally {
            lock.unlock();
        }
    }
}



@Test
public void test_withPut() throws InterruptedException {
    ItemStore itemStore = new ItemStore();
    final String key = "foo";
    final String value = "bar";

    new Thread() {
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
                log.info("slept 3 seconds");
                itemStore.put(key, value);
            } catch (Exception e) {
            }
        }
    }.start();

    log.info("fetching");
    String actual = itemStore.fetchWithTimeout(key, 20);
    log.info("actual = " + actual );
    assertEquals( actual, value );
}

基于来自以下测试的日志:

Based on the logs from the test as below:

2014-10-05 17:52:48 INFO  com.tns.ct.downloader.tests.commons.ItemStoreTest.test_withPut():36 - fetching
2014-10-05 17:52:48 INFO  com.tns.ct.downloader.tests.commons.ItemStore.fetchWithTimeout():30 - store doesn't have foo; keep waiting
2014-10-05 17:52:51 INFO  com.tns.ct.downloader.tests.commons.ItemStoreTest.run():29 - slept 3 seconds
2014-10-05 17:52:51 INFO  com.tns.ct.downloader.tests.commons.ItemStore.put():21 - stored foo
2014-10-05 17:53:08 INFO  com.tns.ct.downloader.tests.commons.ItemStoreTest.test_withPut():38 - actual = bar

似乎 hasItem.signalAll()从未返回过,因为从未发出过标记了所有线程的信号日志。另一个提示是,仅在达到20秒超时时程序才退出。那么,为什么在这种情况下 signalAll()方法被阻止?

it seems that hasItem.signalAll() has never returned, as the signaled all threads log has never been issued. Another clue is that the program exited only when the 20 seconds timeout was reached. So, why is the signalAll() method blocked in this case?

推荐答案

document.SignalAll()的文档


一个实现可能(并且通常确实)要求在调用此方法时当前线程持有与此条件相关联的锁。

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called.

ReentrantLock的文档。 newCondition()


返回的Condition实例使用时与Object监视器方法(wait,notify和notifyAll)支持相同的用法

The returned Condition instance supports the same usages as do the Object monitor methods (wait, notify, and notifyAll) when used with the built-in monitor lock.

如果调用任何Condition等待或信令方法时未持有此锁定,则将抛出IllegalMonitorStateException。

If this lock is not held when any of the Condition waiting or signalling methods are called, then an IllegalMonitorStateException is thrown.

不确定为什么在测试中未抛出IllegalMonitorException,但是可以确定的是,放置线程在调用 signalAll()时没有保持锁

Not sure why an IllegalMonitorException isn't thrown in your test, but what's sure is the the putting thread doesn't hold the lock when it calls signalAll() on the condition.

编辑:正如@Fildor所提到的,可能会引发异常,但会被测试中的空catch块吞没。不要使用空的捕获块。如果您抛出一个运行时异常,而不是吞下捕获的异常,那么它就会变得很明显。

as @Fildor mentions, an exception is probably thrown, but swallowed by the empty catch block in your test. Don't use empty catch blocks. If you threw a runtime exception wrapping the caught exception instead of swallowing it, the problem would become obvious.

这篇关于条件实例signalAll()不返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆