18.5.7. 同步原语

锁:

信号量:

asyncio lock API was designed to be close to classes of the threading module (Lock, Event, Condition, Semaphore, BoundedSemaphore), but it has no timeout parameter. asyncio.wait_for()函数可用于在超时后取消任务。

18.5.7.1. Locks

18.5.7.1.1. Lock

class asyncio.Lock(*, loop=None)

原语锁对象。

原语锁是同步原语,当锁定时不属于特定的协程。原始锁处于两种状态之一,“锁定”或“解锁”。

它是在解锁状态下创建的。它有两个基本方法,acquire()release()当状态解锁时,acquire()将状态更改为锁定并立即返回。当状态被锁定时,acquire()阻塞直到对另一个协程中的release()的调用将其改变为解锁,然后acquire()调用将其重置为锁定并返回。release()方法只能在锁定状态下调用;它将状态更改为已解锁并立即返回。如果尝试释放已解锁的锁,将会引发RuntimeError

当在acquire()中阻塞了多个协程等待状态转为解锁时,只有一个协程在release()调用将状态重置为未锁定时进行;正在处理在acquire()中被阻塞的第一协程。

acquire()是协程,应使用yield from调用。

锁也支持上下文管理协议。(产生 锁定)应用作上下文管理器表达式。

此类为not thread safe

用法:

lock = Lock()
...
yield from lock
try:
    ...
finally:
    lock.release()

上下文管理器用法:

lock = Lock()
...
with (yield from lock):
    ...

可以测试锁定对象的锁定状态:

if not lock.locked():
    yield from lock
else:
    # lock is acquired
    ...
locked()

如果获取到锁,则返回True

coroutine acquire()

获取锁。

此方法阻塞直到被解锁,然后将其设置为锁定并返回True

此方法是协程

release()

释放锁。

当锁被锁定时,将其重置为解锁,然后返回。如果任何其他协程被阻止等待锁被解锁,则只允许其中一个继续。

当在未锁定的锁上调用时,会引发RuntimeError

没有返回值。

18.5.7.1.2. Event

class asyncio.Event(*, loop=None)

事件实现,异步等效于threading.Event

实现事件对象的类。事件管理可以使用set()方法设置为true的标志,并使用clear()方法将其复位为false。wait()方法阻塞,直到标志为真。该标志最初为假。

此类为not thread safe

clear()

将内部标志重置为false。随后,调用wait()的协程将阻塞,直到调用set(),再次将内部标志设置为true。

is_set()

当且仅当内部标志为真时返回True

set()

将内部标志设置为true。所有协程等待它变成真的都被唤醒。标志为真时调用wait()的协程将不会阻塞。

coroutine wait()

阻塞直到内部标志为真。

如果条目上的内部标志为真,则立即返回True否则,阻塞直到另一个协程调用set()将该标志设置为true,然后返回True

此方法是coroutine

18.5.7.1.3. Condition

class asyncio.Condition(lock=None, *, loop=None)

条件实现,异步等效于threading.Condition

这个类实现条件变量对象。条件变量允许一个或多个协程等待,直到它们被另一个协程通知。

如果给出了lock参数,而不是None,则它必须是Lock对象,并且用作基础锁。否则,将创建一个新的Lock对象,并将其用作基础锁。

此类为not thread safe

coroutine acquire()

获取底层锁。

此方法阻塞直到锁定解锁,然后将其设置为锁定并返回True

此方法是coroutine

notify(n=1)

默认情况下,唤醒一个协程等待此条件,如果有的话。如果调用此方法时调用协程未获取锁,则会引发RuntimeError

此方法最多在协程的n唤醒,等待条件变量;如果没有协程在等待,它是无操作的。

注意

唤醒的协程实际上不从其wait()返回,直到它可以重新获取锁。由于notify()不释放锁,其调用者应该。

locked()

如果获取了基础锁,则返回True

notify_all()

唤醒所有协程等待这个条件。此方法的作用类似于notify(),但唤醒所有等待协程而不是一个。如果调用此方法时调用协程未获取锁,则会引发RuntimeError

release()

释放底层锁。

当锁被锁定时,将其重置为解锁,然后返回。如果任何其他协程被阻止等待锁被解锁,则只允许其中一个继续。

当在未锁定的锁上调用时,会引发RuntimeError

没有返回值。

coroutine wait()

等待直到通知。

如果调用此方法时调用协程未获取锁,则会引发RuntimeError

此方法释放底层锁,然后阻塞,直到它被另一个协程中的相同条件变量的notify()notify_all()唤醒。一旦被唤醒,它会重新获取锁定并返回True

此方法是coroutine

coroutine wait_for(predicate)

等待一个谓词变为true。

谓词应该是可调用的,其结果将被解释为布尔值。最终的谓词值是返回值。

此方法是coroutine

18.5.7.2. 信号量

18.5.7.2.1. 信号量

class asyncio.Semaphore(value=1, *, loop=None)

信号量实现。

信号量管理器有一个内部计数器,当调用acquire()时递减,调用release()时递增。计数器永远不会低于零;当acquire()发现它为零时,它阻塞,等待其他协程调用release()

信号量对象也还支持上下文管理协议。

可选参数给出内部计数器的初始值;它默认为1如果给定的值小于0,则会引发ValueError

此类为不是线程安全的

coroutine acquire()

获取信号量。

如果内部计数器在输入时大于零,则将其减1并立即返回True如果在入口处为零,则阻塞,等待直到一些其他协程调用release()使其大于0,然后返回True

此方法是coroutine

locked()

如果不能立即获取信号量,则返回True

release()

释放信号量,将内部计数器递增1。当它在进入时为零,并且另一个协程等待它再次变得大于零时,唤醒协程。

18.5.7.2.2. BoundedSemaphore

class asyncio.BoundedSemaphore(value=1, *, loop=None)

有界信号量实现。Semaphore继承。

此引发release()中的ValueError如果它将增加的值高于初始值。