[英]How to await a Condition without the chance of await being called after signal in Java?
我的代碼中有一個等待/通知機制,基本上像這樣包裝了Lock
和Condition
:
class ConditionWithTimeout { // timeout part omitted
private Lock lock = new ReentrantLock();
private Condition cond = lock.newCondition();
public void doWait() throws InterruptedException {
lock.lock();
cond.await();
lock.unlock();
}
public void doNotify() {
lock.lock();
cond.signalAll();
lock.unlock();
}
}
我的問題是,如果我做這樣的事情:
someFunction();
myCond.doWait();
如果someFunction
在doNotify
上的某個時刻調用doNotify
, myCondition
我可能會等到myCondition
超時,因為doWait
中的someFunction
可能會在此代碼跳至下一行執行myCond.doWait
之前執行。
我通過添加preWaitFn
解決了preWaitFn
:
class ConditionWithTimeout {
private Lock lock = new ReentrantLock();
private Condition cond = lock.newCondition();
private Executor hookExecutor = Executors.newSingleThreadExecutor();
public void doWait() throws InterruptedException {
doWait(() -> {
});
}
public void doWait(Runnable preWaitFn) throws InterruptedException {
lock.lock();
hookExecutor.execute(preWaitFn);
cond.await();
lock.unlock();
}
public void doNotify() {
lock.lock();
cond.signalAll();
lock.unlock();
}
}
和它的作品,但現在這似乎是一個代碼味道對我來說,因為它仍然是可能的doNotify
之前被稱為cond.await
被調用。
所以我的問題是,在這種情況下最佳做法是什么? 我需要阻塞,直到someFunction
完成其工作,但我希望避免出現這種someFunction
情況。
通常的模式是檢查某些邏輯條件,並將該信號用作通知另一線程該條件已更新的手段。 就您而言,一個簡單的標志就足夠了:
private boolean flag = false;
public void doWait() throws InterruptedException {
lock.lock();
try {
// Loop is necessary to avoid spurious wakeup
while (!flag) {
cond.await();
}
} finally {
// Unlock in finally in case exception is thrown
lock.unlock();
}
}
public void doNotify() {
lock.lock();
try {
flag = true;
cond.signalAll();
} finally {
lock.unlock();
}
}
您可以嘗試使用CountDownLatch 。 根據您的用例,這可能不是最佳答案-如果您可以為每個調用創建一個flag對象的新實例,但如果您需要重用一個實例,則可以用。 鏈接的Javadoc頁面包含有關如何使用它的示例。 這基本上是shmosel答案的現成替代品。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.