同步原語?

asyncio 同步原語被設計為與 threading 模塊的類似,但有兩個關鍵注意事項:

  • asyncio 原語不是線程安全的,因此它們不應被用于 OS 線程同步 (而應當使用 threading);

  • 這些同步原語的方法不接受 timeout 參數;請使用 asyncio.wait_for() 函數來執行帶有超時的操作。

asyncio 具有下列基本同步原語:


Lock?

class asyncio.Lock(*, loop=None)?

實現一個用于 asyncio 任務的互斥鎖。 非線程安全。

asyncio 鎖可被用來保證對共享資源的獨占訪問。

使用 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()
coroutine acquire()?

獲取鎖。

此方法會等待直至鎖為 unlocked,將其設為 locked 并返回 True

當有一個以上的協程在 acquire() 中被阻塞則會等待解鎖,最終只有一個協程會被執行。

鎖的獲取是 公平的: 被執行的協程將是第一個開始等待鎖的協程。

release()?

釋放鎖。

當鎖為 locked 時,將其設為 unlocked 并返回。

如果鎖為 unlocked,則會引發 RuntimeError

locked()?

如果鎖為 locked 則返回 True

Event?

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

事件對象。 該對象不是線程安全的。

asyncio 事件可被用來通知多個 asyncio 任務已經有事件發生。

Event 對象會管理一個內部旗標,可通過 set() 方法將其設為 true 并通過 clear() 方法將其設為 falsewait() 方法會阻塞直至該旗標被設為 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())
coroutine wait()?

等待直至事件被設置。

如果事件已被設置,則立即返回 True。 否則將阻塞直至另一個事件調用 set()

set()?

設置事件。

所有等待事件被設置的任務將被立即喚醒。

clear()?

清空(取消設置)事件.

通過 wait() 進行等待的任務現在將會阻塞直至 set() 方法再次被調用。

is_set()?

如果事件已被設置則返回 True

Condition?

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

條件對象。 該對象不是線程安全的。

asyncio 條件原語可被任務用于等待某個事件發生,然后獲取對共享資源的獨占訪問。

在本質上,Condition 對象合并了 EventLock 的功能。 多個 Condition 對象有可能共享一個 Lock,這允許關注于共享資源的特定狀態的不同任務實現對共享資源的協同獨占訪問。

可選的 lock 參數必須為 Lock 對象或 None。 在后一種情況下會自動創建一個新的 Lock 對象。

使用 Condition 的推薦方式是通過 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()
coroutine acquire()?

獲取下層的鎖。

此方法會等待直至下層的鎖為 unlocked,將其設為 locked 并返回 returns True

notify(n=1)?

喚醒最多 n 個正在等待此條件的任務(默認為 1 個)。 如果沒有任務正在等待則此方法為空操作。

鎖必須在此方法被調用前被獲取并在隨后被快速釋放。 如果通過一個 unlocked 鎖調用則會引發 RuntimeError

locked()?

如果下層的鎖已被獲取則返回 True

notify_all()?

喚醒所有正在等待此條件的任務。

此方法的行為類似于 notify(),但會喚醒所有正在等待的任務。

鎖必須在此方法被調用前被獲取并在隨后被快速釋放。 如果通過一個 unlocked 鎖調用則會引發 RuntimeError

release()?

釋放下層的鎖。

在未鎖定的鎖調用時,會引發 RuntimeError 異常。

coroutine wait()?

等待直至收到通知。

當此方法被調用時如果調用方任務未獲得鎖,則會引發 RuntimeError

這個方法會釋放下層的鎖,然后保持阻塞直到被 notify()notify_all() 調用所喚醒。 一旦被喚醒,Condition 會重新獲取它的鎖并且此方法將返回 True

coroutine wait_for(predicate)?

等待直到目標值變為 true

目標必須為一個可調用對象,其結果將被解讀為一個布爾值。 最終的值將為返回值。

Semaphore?

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

信號量對象。 該對象不是線程安全的。

信號量會管理一個內部計數器,該計數器會隨每次 acquire() 調用遞減并隨每次 release() 調用遞增。 計數器的值永遠不會降到零以下;當 acquire() 發現其值為零時,它將保持阻塞直到有某個任務調用了 release()

可選的 value 參數用來為內部計數器賦初始值 (默認值為 1)。 如果給定的值小于 0 則會引發 ValueError

使用 Semaphore 的推薦方式是通過 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()
coroutine acquire()?

獲取一個信號量。

如果內部計數器的值大于零,則將其減一并立即返回 True。 如果其值為零,則會等待直到 release() 并調用并返回 True

locked()?

如果信號量對象無法被立即獲取則返回 True

release()?

釋放一個信號量對象,將內部計數器的值加一。 可以喚醒一個正在等待獲取信號量對象的任務。

不同于 BoundedSemaphoreSemaphore 允許執行的 release() 調用多于 acquire() 調用。

BoundedSemaphore?

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

綁定的信號量對象。 該對象不是線程安全的。

BoundedSemaphore 是特殊版本的 Semaphore,如果在 release() 中內部計數器值增加到初始 value 以上它將引發一個 ValueError


3.7 版后已移除: Acquiring a lock using await lock or yield from lock and/or with statement (with await lock, with (yield from lock)) is deprecated. Use async with lock instead.