同期プリミティブ
ソースコード: :source: `Lib / asyncio / locks.py`
asyncio同期プリミティブは、 threading モジュールのプリミティブと同様に設計されていますが、2つの重要な注意事項があります。
- asyncioプリミティブはスレッドセーフではないため、OSスレッド同期には使用しないでください(そのためにはスレッドを使用してください)。
- これらの同期プリミティブのメソッドは、 timeout 引数を受け入れません。
asyncio.wait_for()
関数を使用して、タイムアウト付きの操作を実行します。
asyncioには、次の基本的な同期プリミティブがあります。
ロック
- class asyncio.Lock(\*, loop=None)
asyncioタスクのミューテックスロックを実装します。 スレッドセーフではありません。
非同期ロックを使用して、共有リソースへの排他的アクセスを保証できます。
ロックを使用するための好ましい方法は、 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()
ロックを解除します。
ロックがロックになったら、ロック解除にリセットして戻ります。
ロックがロック解除の場合、 RuntimeError が発生します。
- 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オブジェクトは、 Event と Lock の機能を組み合わせたものです。 複数のConditionオブジェクトで1つのロックを共有することができます。これにより、共有リソースの特定の状態に関係するさまざまなタスク間で共有リソースへの排他的アクセスを調整できます。
オプションの 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)をウェイクアップします。 待機中のタスクがない場合、このメソッドはノーオペレーションです。
このメソッドが呼び出される前にロックを取得し、直後に解放する必要があります。 ロック解除ロックで呼び出された場合、 RuntimeError エラーが発生します。
- locked()
基になるロックが取得された場合は、
True
を返します。
- notify_all()
この状態で待機しているすべてのタスクをウェイクアップします。
このメソッドは notify()のように機能しますが、待機中のすべてのタスクをウェイクアップします。
このメソッドが呼び出される前にロックを取得し、直後に解放する必要があります。 ロック解除ロックで呼び出された場合、 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()
セマフォを解放し、内部カウンタを1つインクリメントします。 セマフォの取得を待機しているタスクをウェイクアップできます。
BoundedSemaphore とは異なり、 Semaphore では、
acquire()
呼び出しよりも多くのrelease()
呼び出しを行うことができます。
BoundedSemaphore
- class asyncio.BoundedSemaphore(value=1, \*, loop=None)
境界付きセマフォオブジェクト。 スレッドセーフではありません。
バウンドセマフォはセマフォのバージョンであり、内部カウンターが初期の値を超えると、 release()で ValueError が発生します。
バージョン3.7以降非推奨: await lock
またはyield from lock
および/または with ステートメント(with await lock
、with (yield from lock)
)は非推奨です。 代わりにasync with lock
を使用してください。