【发布时间】:2018-07-25 10:30:43
【问题描述】:
我想问一下asyncio.Condition。我不熟悉这个概念,但我从学生时代就知道并理解锁、信号量和队列。
我找不到很好的解释或典型用例,只有this example。我看了看源码。核心功能是通过期货 FIFO 实现的。每个等待的协程都会添加一个新的 future 并等待它。另一个协程可能会调用notify(),它会设置来自 FIFO 的一个或多个未来的结果,并唤醒相同数量的等待协程。到目前为止真的很简单。
但是,实现和使用比这更复杂。等待的协程必须首先获取与条件关联的锁才能等待(wait() 在等待时释放它)。此外,通知者必须获得一个锁才能通知()。这导致在每个操作之前with 声明:
async with condition:
# condition operation (wait or notify)
否则RuntimeError 发生。
我不明白拥有这个锁的意义。我们需要用锁保护什么资源?在 asyncio 中,事件循环中可能总是只有一个协程执行,没有线程已知的“关键部分”。
这个锁是真的需要(为什么?)还是只是为了与线程代码兼容?
我的第一个想法是为了兼容性,但在这种情况下,为什么他们不删除锁而保留使用?即制作
async with condition:
基本上是一个可选的无操作。
【问题讨论】:
-
如果你解除锁定,你有一个事件,而不是一个条件。
-
在 asyncio 中,事件循环中可能总是只有一个协程在执行,没有线程已知的“关键部分”。这仅在关键时成立部分没有
await。确实,对于线程,您必须锁定一切(或使用原子指令),但在 asyncio 中,如果有可能暂停,您仍然必须锁定,只要存在await,就会出现这种情况。 -
@MartijnPieters 我明天会研究你的完整答案,但我想对你的评论做出反应。有区别:
Event: - 如果在await wait()之前调用set(),则等待立即返回。Condition:如果在await.wait()之前调用notify(),则等待阻塞。我认为锁不参与其中,这就是为什么没有锁的条件与事件不同。 -
@VPfB:这当然涉及到锁,因为没有锁你不能等待或通知。
-
@VPfB:是的,事件和条件有所不同,我在简化。如果您要使用事件和锁实现条件原语之类的东西,则必须确保在等待之前清除事件,并在每次
wait()返回时清除事件。如果您不需要锁定,那么您可能正在寻找事件而不是条件。
标签: python python-asyncio