同期プリミティブ¶
ソースコード: Lib/asyncio/locks.py
asyncio の同期プリミティブは threading
モジュールのそれと類似するようにデザインされていますが、2つの重要な注意事項があります:
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()
Deprecated since version 3.8, will be removed in version 3.10: loop パラメータ。
-
coroutine
acquire
()¶ ロックを獲得します。
このメソッドはロックが 解除される まで待機し、ロックを ロック状態 に変更して
True
を返します。複数のコルーチンが
acquire()
メソッドによりロックの解除を待ち受けている場合、最終的にただひとつのコルーチンが実行されます。ロックの獲得は 公平 です: すなわちロックを獲得して実行されるコルーチンは、最初にロックの待ち受けを開始したコルーチンです。
-
release
()¶ ロックを解放します。
ロックが ロック状態 の場合、 ロックを 解除状態 にしてリターンします。
ロックが 解除状態 の場合、
RuntimeError
例外が送出されます。
-
locked
()¶ ロック状態 の場合に
True
を返します。
-
coroutine
Event¶
-
class
asyncio.
Event
(*, loop=None)¶ イベントオブジェクトです。スレッドセーフではありません。
asyncio イベントは、複数の asyncio タスクに対して何らかのイベントが発生したことを通知するために使うことができます。
Event オブジェクトは内部フラグを管理します。フラグの値は
set()
メソッドにより true に、またclear()
メソッドにより false に設定することができます。wait()
メソッドはフラグが true になるまで処理をブロックします。フラグの初期値は false です。Deprecated since version 3.8, will be removed in version 3.10: loop パラメータ。
以下はプログラム例です:
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
()¶ イベントをセットします。
イベントがセットされるまで待機している全てのタスクは、即座に通知を受けて実行を再開します。
-
is_set
()¶ イベントがセットされている場合
True
を返します。
-
coroutine
Condition¶
-
class
asyncio.
Condition
(lock=None, *, loop=None)¶ 条件変数オブジェクトです。スレッドセーフではありません。
asyncio 条件プリミティブは何らかのイベントが発生するのを待ち受け、そのイベントを契機として共有リソースへの排他的なアクセスを得るために利用することができます。
本質的に、 Condition オブジェクトは
Event
と aLock
の2つのクラスの機能を組み合わせたものです。複数の Condition オブジェクトが単一の Lock を共有することでができます。これにより、共有リソースのそれぞれの状態に関連する異なるタスクの間で、そのリソースへの排他的アクセスを調整することが可能になります。オプション引数 lock は
Lock
またはNone
でなければなりません。後者の場合自動的に新しい Lock オブジェクトが生成されます。Deprecated since version 3.8, will be removed in version 3.10: loop パラメータ。
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
()¶ 下層でのロックを獲得します。
このメソッドは下層のロックが 解除される まで待機し、ロックを ロック状態 に変更して
True
を返します。
-
notify
(n=1)¶ この条件を待ち受けている最大で n 個のタスク (n のデフォルト値は 1) を起動します。待ち受けているタスクがいない場合、このメソッドは何もしません。
このメソッドが呼び出される前にロックを獲得しておかなければなりません。また、メソッド呼び出し後速やかにロックを解除しなければなりません。 解除された ロックとと共に呼び出された場合、
RuntimeError
例外が送出されます。
-
locked
()¶ 下層のロックを獲得していれば
True
を返します。
-
notify_all
()¶ この条件を待ち受けている全てのタスクを起動します。
このメソッドは
notify()
と同じように振る舞いますが、待ち受けている全てのタスクを起動します。このメソッドが呼び出される前にロックを獲得しておかなければなりません。また、メソッド呼び出し後速やかにロックを解除しなければなりません。 解除された ロックとと共に呼び出された場合、
RuntimeError
例外が送出されます。
-
release
()¶ 下層のロックを解除します。
アンロック状態のロックに対して呼び出された場合、
RuntimeError
が送出されます。
-
coroutine
wait
()¶ 通知を受けるまで待機します。
このメソッドが呼び出された時点で呼び出し元のタスクがロックを獲得していない場合、
RuntimeError
例外が送出されます。このメソッドは下層のロックを解除し、その後
notify()
またはnotify_all()
の呼び出しによって起動されるまで処理をブロックします。いったん起動されると、 Condition は再びロックを獲得し、メソッドはTrue
を返します。
-
coroutine
wait_for
(predicate)¶ 引数 predicate の条件が 真 になるまで待機します。
引数 predicate は戻り値が真偽地として解釈可能な呼び出し可能オブジェクトでなければなりません。 predicate の最終的な値が戻り値になります。
-
coroutine
Semaphore¶
-
class
asyncio.
Semaphore
(value=1, *, loop=None)¶ セマフォオブジェクトです。スレッドセーフではありません。
セマフォは内部のカウンターを管理しています。カウンターは
acquire()
メソッドの呼び出しによって減算され、release()
メソッドの呼び出しによって加算されます。カウンターがゼロを下回ることはありません。acquire()
メソッドが呼び出された時にカウンターがゼロになっていると、セマフォは処理をブロックし、他のタスクがrelease()
メソッドを呼び出すまで待機します。オプション引数 value は内部カウンターの初期値を与えます (デフォルトは
1
です)。 指定された値が0
より小さい場合、ValueError
例外が送出されます。Deprecated since version 3.8, will be removed in version 3.10: loop パラメータ。
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
()¶ セマフォを獲得します。
内部カウンターがゼロより大きい場合、カウンターを1つ減算して即座に
True
を返します。内部カウンターがゼロの場合、release()
が呼び出されるまで待機してからTrue
を返します。
-
locked
()¶ セマフォを直ちに獲得できない場合
True
を返します。
-
release
()¶ セマフォを解放し、内部カウンターを1つ加算します。セマフォ待ちをしているタスクを起動する可能性があります。
BoundedSemaphore
と異なり、Semaphore
はrelease()
をacquire()
よりも多く呼び出すことを許容します。
-
coroutine
BoundedSemaphore¶
-
class
asyncio.
BoundedSemaphore
(value=1, *, loop=None)¶ 有限セマフォオブジェクトです。スレッドセーフではありません。
有限セマフォは
Semaphore
の一種で、release()
メソッドの呼び出しにより内部カウンターが 初期値 よりも増加してしまう場合はValueError
例外を送出します。Deprecated since version 3.8, will be removed in version 3.10: loop パラメータ。
バージョン 3.9 で変更: await lock
や yield from lock
およびそれらと with
文との組み合わせ (すなわち with await lock
や with (yield from lock)
) によるロックの獲得は削除されました。代わりに async with lock
を使ってください。