Synchronization Primitives

源代码: Lib/asyncio/locks.py


asyncio 同步 Primitives 的设计类似于threading模块的 Primitives,但有两个重要警告:

  • 异步 Primitives 不是线程安全的,因此不应将它们用于 OS 线程同步(为此使用threading);

  • 这些同步 Primitives 的方法不接受* timeout *参数;使用asyncio.wait_for()函数执行超时操作。

asyncio 具有以下基本同步 Primitives:


Lock

    • class * asyncio. Lock(** loop = None *)
    • 为异步任务实现互斥锁。不是线程安全的。

异步锁可用于保证对共享资源的独占访问。

使用 Lock 的首选方式是async with语句:

lock = asyncio.Lock()

# ... later
async with lock:
    # access shared state

等效于:

lock = asyncio.Lock()

# ... later
await lock.acquire()
try:
    # access shared state
finally:
    lock.release()

从 3.8 版开始不推荐使用,将在 3.10 版中删除:* loop *参数。

  • 协程 acquire()
    • 获取锁。

该方法一直等到锁定被* unlocked 解锁,将其设置为 locked *并返回True

如果在acquire()中阻止了一个协程 await 释放锁,则finally只有一个协程进行。

获得锁是“公平的”:continue 执行的协程将是开始 await 锁的第一个协程。

  • release ( )
    • 释放锁。

当锁定为* locked 时,将其重置为 unlocked *并返回。

如果锁是* unlocked *,则引发RuntimeError

  • locked ( )
    • 如果锁定为* locked *,则返回True

Event

    • class * asyncio. Event(** loop = None *)
    • 事件对象。不是线程安全的。

异步事件可用于通知多个异步任务某个事件已发生。

事件对象 Management 一个内部标志,该内部标志可以passset()方法设置为* true ,并passclear()方法设置为 false wait()方法阻塞,直到标志设置为 true 为止。该标志最初设置为 false *。

从 3.8 版开始不推荐使用,将在 3.10 版中删除:* loop *参数。

Example:

async def waiter(event):
    print('waiting for it ...')
    await event.wait()
    print('... got it!')

async def main():
    # Create an Event object.
    event = asyncio.Event()

    # Spawn a Task to wait until 'event' is set.
    waiter_task = asyncio.create_task(waiter(event))

    # Sleep for 1 second and set the event.
    await asyncio.sleep(1)
    event.set()

    # Wait until the waiter task is finished.
    await waiter_task

asyncio.run(main())
  • 协程 wait()
    • await 事件被设置。

如果设置了事件,请立即返回True。否则,阻塞直到另一个任务调用set()

  • set ( )
    • 设置事件。

await 事件设置的所有任务将立即唤醒。

  • clear ( )
    • 清除(取消设置)事件。

现在,在wait()上 await 的任务将阻塞,直到再次调用set()方法。

  • is_set ( )
    • 如果设置了事件,则返回True

Condition

    • class * asyncio. Condition(* lock = None **,* loop = None *)
    • 条件对象。不是线程安全的。

任务可以使用异步条件 Primitives 来 await 某个事件发生,然后获得对共享资源的独占访问。

本质上,Condition 对象结合了EventLock的Function。可能有多个 Condition 对象共享一个 Lock,这允许在对该共享资源的特定状态感兴趣的不同任务之间协调对共享资源的排他访问。

可选的* lock *参数必须是Lock对象或None。在后一种情况下,将自动创建一个新的 Lock 对象。

从 3.8 版开始不推荐使用,将在 3.10 版中删除:* loop *参数。

使用条件的首选方式是async with语句:

cond = asyncio.Condition()

# ... later
async with cond:
    await cond.wait()

等效于:

cond = asyncio.Condition()

# ... later
await cond.acquire()
try:
    await cond.wait()
finally:
    cond.release()
  • 协程 acquire()
    • 获取基础锁。

该方法一直等到基础锁定被* unlocked 解锁,将其设置为 locked *并返回True

  • notify(* n = 1 *)
    • 在这种情况下最多唤醒* n *个任务(默认为 1 个)。如果没有任务在 await,则该方法为无操作。

必须在调用此方法之前获取该锁,并在此之后不久将其释放。如果使用“ *解锁”锁调用,则会引发RuntimeError错误。

  • locked ( )

    • 如果已获得基础锁,则返回True
  • notify_all ( )

    • 唤醒所有在这种情况下 await 的任务。

此方法的作用类似于notify(),但是唤醒所有 await 的任务。

必须在调用此方法之前获取该锁,并在此之后不久将其释放。如果使用“ *解锁”锁调用,则会引发RuntimeError错误。

  • release ( )
    • 释放基础锁。

在解锁的锁上调用时,将引发RuntimeError

  • 协程 wait()
    • 等到收到通知。

如果在调用此方法时调用任务尚未获取锁,则会引发RuntimeError

此方法释放基础锁,然后阻塞,直到被notify()notify_all()调用唤醒。唤醒后,Condition 重新获取其锁定,此方法返回True

  • 协程 wait_for(谓词)
    • 等到谓词变为* true *。

谓词必须是可调用的,其结果将被解释为布尔值。finally值是返回值。

Semaphore

    • class * asyncio. Semaphore(* value = 1 **,* loop = None *)
    • signal 量对象。不是线程安全的。

signal 量 Management 一个内部计数器,该内部计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不能低于零。当acquire()发现它为零时,它将阻塞,直到某些任务调用release()为止。

可选的* value *参数给出内部计数器的初始值(默认为1)。如果给定值小于0,则引发ValueError

从 3.8 版开始不推荐使用,将在 3.10 版中删除:* loop *参数。

使用 signal 量的首选方法是async with语句:

sem = asyncio.Semaphore(10)

# ... later
async with sem:
    # work with shared resource

等效于:

sem = asyncio.Semaphore(10)

# ... later
await sem.acquire()
try:
    # work with shared resource
finally:
    sem.release()
  • 协程 acquire()
    • 获取 signal 量。

如果内部计数器大于零,则将其递减一并立即返回True。如果为零,请 await 直到调用release()并返回True

  • locked ( )

    • 如果无法立即获取 signal 量,则返回True
  • release ( )

    • 释放 signal 量,使内部计数器增加一。可以唤醒 await 获取 signal 量的任务。

BoundedSemaphore不同,Semaphore允许进行release()通话多于acquire()通话。

BoundedSemaphore

    • class * asyncio. BoundedSemaphore(* value = 1 **,* loop = None *)
    • 有界 signal 量对象。不是线程安全的。

有界 signal 量是Semaphore的一个版本,如果它将内部计数器增加到初始* value *以上,则会在release()中引发ValueError

从 3.8 版开始不推荐使用,将在 3.10 版中删除:* loop *参数。


从 3.7 版开始不推荐使用:不推荐使用await lockyield from lock和/或with语句(with await lockwith (yield from lock))获取锁。改用async with lock