tornado.locks
– 同期プリミティブ¶
バージョン 4.2 で追加。
標準ライブラリがスレッドに提供するものと同様の同期プリミティブを使用して、コルーチンを調整します。これらのクラスは、標準ライブラリのasyncio パッケージで提供されているものと非常によく似ています。
警告
これらのプリミティブは実際にはスレッドセーフではなく、標準ライブラリのthreading
モジュールのものとは置き換えられません。これらは、マルチスレッドアプリケーションで共有オブジェクトを保護するためではなく、シングルスレッドアプリケーションでTornadoコルーチンを調整することを目的としています。
Condition¶
- class tornado.locks.Condition[source]¶
Condition は、1つ以上のコルーチンが通知されるまで待機できるようにします。
標準の
threading.Condition
と似ていますが、取得および解放される基盤となるロックは必要ありません。Condition
を使用すると、コルーチンは他のコルーチンによって通知されるのを待つことができます。import asyncio from tornado import gen from tornado.locks import Condition condition = Condition() async def waiter(): print("I'll wait right here") await condition.wait() print("I'm done waiting") async def notifier(): print("About to notify") condition.notify() print("Done notifying") async def runner(): # Wait for waiter() and notifier() in parallel await gen.multi([waiter(), notifier()]) asyncio.run(runner())
I'll wait right here About to notify Done notifying I'm done waiting
wait
は、オプションのtimeout
引数を取ります。これは絶対的なタイムスタンプです。io_loop = IOLoop.current() # Wait up to 1 second for a notification. await condition.wait(timeout=io_loop.time() + 1)
…または、現在の時刻からの相対的なタイムアウトのための
datetime.timedelta
です。# Wait up to 1 second. await condition.wait(timeout=datetime.timedelta(seconds=1))
期限前に通知がない場合は、Falseを返します。
Event¶
- class tornado.locks.Event[source]¶
イベントは、内部フラグがTrueに設定されるまでコルーチンをブロックします。
threading.Event
に似ています。コルーチンは、イベントが設定されるのを待つことができます。設定されると、
yield event.wait()
への呼び出しは、イベントがクリアされない限りブロックされません。import asyncio from tornado import gen from tornado.locks import Event event = Event() async def waiter(): print("Waiting for event") await event.wait() print("Not waiting this time") await event.wait() print("Done") async def setter(): print("About to set the event") event.set() async def runner(): await gen.multi([waiter(), setter()]) asyncio.run(runner())
Waiting for event About to set the event Not waiting this time Done
Semaphore¶
- class tornado.locks.Semaphore(value: int = 1)[source]¶
ブロックする前に一定回数取得できるロック。
Semaphoreは、
release
呼び出しの数からacquire
呼び出しの数を引いた数、プラス初期値を表すカウンタを管理します。acquire
メソッドは、カウンタを負にすることなく返ることができるまで必要に応じてブロックします。Semaphoreは、共有リソースへのアクセスを制限します。2つのワーカーが同時にアクセスできるようにするには
import asyncio from tornado import gen from tornado.locks import Semaphore sem = Semaphore(2) async def worker(worker_id): await sem.acquire() try: print("Worker %d is working" % worker_id) await use_some_resource() finally: print("Worker %d is done" % worker_id) sem.release() async def runner(): # Join all workers. await gen.multi([worker(i) for i in range(3)]) asyncio.run(runner())
Worker 0 is working Worker 1 is working Worker 0 is done Worker 2 is working Worker 1 is done Worker 2 is done
ワーカー0と1は同時に実行できますが、ワーカー2はワーカー0によってセマフォが一度解放されるまで待ちます。
セマフォは非同期コンテキストマネージャとして使用できます。
async def worker(worker_id): async with sem: print("Worker %d is working" % worker_id) await use_some_resource() # Now the semaphore has been released. print("Worker %d is done" % worker_id)
古いバージョンのPythonとの互換性のために、
acquire
はコンテキストマネージャであるため、worker
は次のように書くこともできます。@gen.coroutine def worker(worker_id): with (yield sem.acquire()): print("Worker %d is working" % worker_id) yield use_some_resource() # Now the semaphore has been released. print("Worker %d is done" % worker_id)
バージョン4.3で変更: Python 3.5で
async with
サポートを追加。
BoundedSemaphore¶
- class tornado.locks.BoundedSemaphore(value: int = 1)[source]¶
release()が何回も呼び出されるのを防ぐセマフォ。
release
がセマフォの値を初期値を超えて増分しようとすると、ValueError
を発生させます。セマフォは主に容量が限られたリソースを保護するために使用されるため、セマフォが何回も解放されることはバグの兆候です。
Lock¶
- class tornado.locks.Lock[source]¶
コルーチン用のロック。
Lockはロック解除状態で開始され、
acquire
によってすぐにロックされます。ロックされている間、acquire
をyieldするコルーチンは、別のコルーチンがrelease
を呼び出すまで待ちます。ロックされていないロックを解放しようとすると、
RuntimeError
が発生します。Lockは、
async with
ステートメントを使用して非同期コンテキストマネージャとして使用できます。>>> from tornado import locks >>> lock = locks.Lock() >>> >>> async def f(): ... async with lock: ... # Do something holding the lock. ... pass ... ... # Now the lock is released.
古いバージョンのPythonとの互換性のために、
acquire
メソッドは非同期的に通常のコンテキストマネージャを返します。>>> async def f2(): ... with (yield lock.acquire()): ... # Do something holding the lock. ... pass ... ... # Now the lock is released.
バージョン4.3で変更: Python 3.5で
async with
サポートを追加。- acquire(timeout: Optional[Union[float, timedelta]] = None) Awaitable[_ReleasingContextManager] [source]¶
ロックを試みます。awaitableを返します。
tornado.util.TimeoutError
をタイムアウト後に発生させるawaitableを返します。
- release() None [source]¶
ロックを解除します。
acquire
を待っているコルーチンの中で最初に来たものがロックを取得します。ロックされていない場合、
RuntimeError
を発生させます。