gpt4 book ai didi

java - 如何在 Java 中等待条件而不会在信号后调用等待?

转载 作者:行者123 更新时间:2023-12-02 03:07:07 25 4
gpt4 key购买 nike

我的代码中有一个等待/通知机制,它基本上包装了 LockCondition,如下所示:

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();

如果someFunctionmyCondition上的某个时刻调用doNotify,我可能会等到myCondition次因为 someFunction 中的 doWait 可能会在该代码跳转到下一行执行 myCond.doWait 之前执行。

我通过添加 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();
}
}

现在它可以工作了,但这对我来说似乎是一种代码味道,因为仍然有可能在调用 cond.await 之前调用 doNotify

所以我的问题是,在这种情况下的最佳实践是什么?我需要阻塞,直到 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();
}
}

关于java - 如何在 Java 中等待条件而不会在信号后调用等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41578392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com