同期プリミティブ—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/asyncio-sync
移動先:案内検索

同期プリミティブ

ソースコード: :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オブジェクトは、 EventLock の機能を組み合わせたものです。 複数の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 lockwith (yield from lock))は非推奨です。 代わりにasync with lockを使用してください。