同步原语 — Python 文档

来自菜鸟教程
Python/docs/3.9/library/asyncio-sync
跳转至:导航、​搜索

同步原语

源代码: :source:`Lib/asyncio/locks.py`



asyncio 同步原语被设计为类似于 threading 模块的那些,但有两个重要的警告:

  • asyncio 原语不是线程安全的,因此它们不应该用于 OS 线程同步(为此使用 threading);
  • 这些同步原语的方法不接受 timeout 参数; 使用 asyncio.wait_for() 函数执行超时操作。

asyncio 具有以下基本同步原语:



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()
release()

释放锁。

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

如果锁是 unlocked,则会引发 RuntimeError

locked()

如果锁是 locked,则返回 True


事件

class asyncio.Event(\*, loop=None)

一个事件对象。 不是线程安全的。

一个 asyncio 事件可用于通知多个 asyncio 任务某个事件已经发生。

事件对象管理一个内部标志,可以使用 set() 方法将其设置为 true,并使用 clear()[ 重置为 false[ X153X] 方法。 wait() 方法阻塞,直到标志设置为 true。 该标志最初设置为 false

例子:

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())
set()

设置事件。

所有等待事件设置的任务将立即被唤醒。

clear()

清除(取消设置)事件。

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

is_set()

如果设置了事件,则返回 True


状况

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

一个条件对象。 不是线程安全的。

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

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

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

使用条件的首选方法是 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()
notify(n=1)

在此条件下最多唤醒 n 个任务(默认为 1 个)。 如果没有任务在等待,则该方法为空操作。

必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 unlocked 锁调用,则会引发 RuntimeError 错误。

locked()

如果获取了底层锁,则返回 True

notify_all()

唤醒所有在此条件下等待的任务。

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

必须在调用此方法之前获取锁,并在不久之后释放锁。 如果使用 unlocked 锁调用,则会引发 RuntimeError 错误。

release()

释放底层锁。

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


信号

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

一个信号量对象。 不是线程安全的。

信号量管理一个内部计数器,该计数器由每个 acquire() 调用递减,并由每个 release() 调用递增。 计数器永远不会低于零; 当 acquire() 发现它为零时,它会阻塞,直到某个任务调用 release()

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

使用信号量的首选方法是 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()
locked()

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

release()

释放信号量,将内部计数器加一。 可以唤醒一个等待获取信号量的任务。

BoundedSemaphore 不同,Semaphore 允许进行比 acquire() 调用更多的 release() 调用。


有界信号量

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

有界信号量对象。 不是线程安全的。

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



3.9 版更改:使用 await lockyield from lock 和/或 with 语句获取锁(with await lockwith (yield from lock)) 被移除。 请改用 async with lock