VPf*_*PfB 8 python python-asyncio
我想问一下asyncio.Condition。我不熟悉这个概念,但我从学生时代就知道并理解锁、信号量和队列。
我找不到很好的解释或典型的用例,只是这个例子。我看了一下源码。核心功能是通过期货的先进先出实现的。每个等待的协程都会添加一个新的未来并等待它。另一个协程可能会调用notify()它从 FIFO 设置一个或多个期货的结果,并唤醒相同数量的等待协程。到目前为止真的很简单。
但是,实现和使用比这更复杂。等待协程必须首先获取与条件关联的锁,以便能够等待(并wait()在等待时释放它)。此外,通知程序必须获得一个锁才能通知()。这导致with在每个操作之前声明:
async with condition:
# condition operation (wait or notify)
Run Code Online (Sandbox Code Playgroud)
否则会发生RuntimeError。
我不明白拥有这个锁的意义。我们需要用锁保护哪些资源?在 asyncio 中,事件循环中总是只有一个协程在执行,没有线程中已知的“临界区”。
这个锁真的需要(为什么?)还是只是为了与线程代码兼容?
我的第一个想法是为了兼容性,但在这种情况下,为什么他们在保留使用的同时不删除锁?即制作
async with condition:
Run Code Online (Sandbox Code Playgroud)
基本上是可选的无操作。
这个问题的答案与threading.Condition 与 threading.Event的答案基本相同;没有锁的条件是事件,而不是条件(*)。
条件用于表示资源可用。等待条件的任何人都可以使用该资源,直到他们完成它。为了确保没有其他人可以使用该资源,您需要锁定该资源:
resource = get_some_resource()
async with resource.condition:
await resource.condition.wait()
# this resource is mine, no-one will touch it
await resource.do_something_async()
# lock released, resource is available again for the next user
Run Code Online (Sandbox Code Playgroud)
注意wait()恢复后锁是如何不释放的!在锁被释放之前,没有其他等待相同条件的协程可以继续,对资源的访问通过锁被排他。注意锁在等待时被释放,所以其他协程可以将自己添加到队列中,但是为了wait()最终返回必须首先重新获取锁。
如果您不需要协调对共享资源的访问,请使用事件;条件基本上是一个锁和事件组合成一个原语,避免常见的实现陷阱。
请注意,多个条件可以共享锁。这将使您向特定阶段发出信号,而其他协程可以等待该特定阶段到达。共享锁将协调对单个资源的访问,但在启动每个阶段时会发出不同的信号。
对于线程,所提供条件的典型用例是单个生产者,多个消费者都在等待来自生产者的项目进行处理。工作队列是共享资源,生产者获取条件锁将一个项目推入队列,然后调用notify(),此时等待条件的下一个消费者获得锁(当它从 返回时wait())并且可以删除该项目从队列开始工作。这并不能完全转化为基于协程的应用程序,因为协程没有线程系统所具有的闲置等待工作要做的问题,只需启动消费者协程就容易得多-根据需要设置例程(可能使用信号量来设置上限)。
也许一个更好的例子是aioimaplib库,它完全支持 IMAP4 事务。这些事务是异步的,但您需要访问共享连接资源。因此,库使用单个 Condition 对象并wait_for()等待特定状态到达,从而为等待该事务状态的协程提供独占连接访问权限。
(*):事件与条件有不同的用例,因此行为与没有锁定的条件略有不同。一旦设置,事件需要明确清除,而条件在使用时“自动清除”,并且在没有人等待条件时永远不会“设置”。但是,如果您想在任务之间发出信号并且不需要控制对共享资源的访问,那么您可能需要一个事件。
| 归档时间: |
|
| 查看次数: |
3233 次 |
| 最近记录: |