python条件变量`wait_for`谓词没有立即返回
Posted
技术标签:
【中文标题】python条件变量`wait_for`谓词没有立即返回【英文标题】:python condition variable `wait_for`predicate not immediately returned 【发布时间】:2021-09-24 01:27:09 【问题描述】:我正在尝试实现一个同步端点,将作业排入队列,等待作业完成,然后返回结果。
lock = Condition()
def predicate(job_in_queue):
job_in_queue.refresh()
print(job_in_queue.get_status())
print(datetime.datetime.now())
if job_in_queue.get_status() == "finished":
return True
return False
print(datetime.datetime.now())
with lock:
if lock.wait_for(lambda: predicate(job), timeout=10):
print("indeed notified")
else:
print("failed to notify")
print(datetime.datetime.now())
print(datetime.datetime.now())
return job.result
python条件变量wait_for
方法wait_for(predicate, timeout=None)
,会停在这一行,等到callable传入predicate
,返回True
,然后继续后面的代码。参考the documentation。
但是,根据我的打印行,predicate
似乎没有被经常检查。它只在第一次传入/第一次调用wait_for
时检查一次,然后它统计空闲并且只在t=timeout
秒后检查它第二次,其中timeout
是我通过的数字在我的打印行中,它仅在 10 秒后检查 predicate
(我在上面的代码中指定的 timeout
值)。
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT 2021-07-15 05:48:23.954320
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT queued
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT 2021-07-15 05:48:23.974196
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT finished
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT 2021-07-15 05:48:33.986337
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT indeed notified
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT 2021-07-15 05:48:33.987215
2021-07-15T13:48:33.98+0800 [APP/PROC/WEB/0] OUT 2021-07-15 05:48:33.987233
我进一步验证了这个问题确实是 predicate
没有通过将 timeout
更改为 15 来不断检查,并且它再次仅在 15 秒后检查 predicate
的结果。
有没有办法让predicate
不断检查这里?不是while True
忙等待,因为它会占用 CPU(并且永远不会通过代码审查)。或者threading.Condition.wait_for
是正确的方式吗?
【问题讨论】:
【参考方案1】:Condition 对象的目的是同步两个或多个线程的活动。当 Thread-1 调用 Condition.wait
时,它会被阻塞。因此,它不可能按照您的意愿检查谓词何时变为真。相反,它必须等待 Thread-2 做一些可能导致谓词变为真的事情。此时,Thread-2 应该通知 Condition 对象。对notify
的调用导致 Thread-1 唤醒并检查谓词。如果谓词现在为真,Thread-1 继续执行;否则会再次阻塞。
在文档中它说:
"忽略超时特性,调用这个方法大致相当于写:
while not predicate():
cv.wait()
"
如果您包含超时值,则 Thread-1 在超时间隔后唤醒,而不管其他线程是否已调用 notify。正如您所观察到的,这会导致检查谓词。
如果您想以合理的频率检查谓词,请提供足够短的超时时间或 确保另一个线程在适当的时间发出通知调用。
但是,如果您不使用它来同步两个或更多线程,那么 Condition 是错误的工具。如果需要紧密循环,请编写紧密循环。
【讨论】:
以上是关于python条件变量`wait_for`谓词没有立即返回的主要内容,如果未能解决你的问题,请参考以下文章
C++ std::condition_variable wait() wait_for() 区别 怎么用 实例
Python3 asyncio:wait_for()通信()超时,如何获得部分结果?