同步原語?
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。
-
coroutine
Event?
-
class
asyncio.Event(*, loop=None)? 事件對象。 該對象不是線程安全的。
asyncio 事件可被用來通知多個 asyncio 任務已經有事件發生。
Event 對象會管理一個內部旗標,可通過
set()方法將其設為 true 并通過clear()方法將其設為 false。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()? 設置事件。
所有等待事件被設置的任務將被立即喚醒。
-
is_set()? 如果事件已被設置則返回
True。
-
Condition?
-
class
asyncio.Condition(lock=None, *, loop=None)? 條件對象。 該對象不是線程安全的。
asyncio 條件原語可被任務用于等待某個事件發生,然后獲取對共享資源的獨占訪問。
在本質上,Condition 對象合并了
Event和Lock的功能。 多個 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。
目標必須為一個可調用對象,其結果將被解讀為一個布爾值。 最終的值將為返回值。
-
coroutine
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()
-
locked()? 如果信號量對象無法被立即獲取則返回
True。
-
release()? 釋放一個信號量對象,將內部計數器的值加一。 可以喚醒一個正在等待獲取信號量對象的任務。
不同于
BoundedSemaphore,Semaphore允許執行的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.
