Python 3.4 の新しい asyncio を使用して、ロック/セマフォのセットから利用可能な最初のロック/セマフォを取得するにはどうすればよいですか?
私が行ったアプローチは を使用し、取得できたら保留中の をwait(return_when=FIRST_COMPLETED)
すべてキャンセルするというものでした。acquire()
しかし、これが微妙なバグ/競合状態を引き起こす可能性があることを懸念しており、よりエレガントな方法があると感じています.
import asyncio as aio
@aio.coroutine
def run():
sem1, sem2 = (aio.Semaphore(), aio.Semaphore())
print('initial:', sem1, sem2)
a = aio.async(sleep(sem1, 1)) # acquire sem1
print('just after sleep:', sem1, sem2)
done, pending = yield from aio.wait([sem1.acquire(), sem2.acquire()], return_when=aio.FIRST_COMPLETED)
print('done:', done)
print('pending:', pending)
for task in pending:
task.cancel()
print('after cancel:', sem1, sem2)
yield from aio.wait([a])
print('after wait:', sem1, sem2)
@aio.coroutine
def sleep(sem, i):
with (yield from sem):
yield from aio.sleep(i)
if __name__ == "__main__":
aio.get_event_loop().run_until_complete(run())
上記のコードは次のとおりです (メモリアドレスを編集):
initial: <asyncio.locks.Semaphore object at 0x1 [unlocked,value:1]> <asyncio.locks.Semaphore object at 0x2 [unlocked,value:1]>
just after sleep: <asyncio.locks.Semaphore object at 0x1 [unlocked,value:1]> <asyncio.locks.Semaphore object at 0x2 [unlocked,value:1]>
done: {Task(<acquire>)<result=True>}
pending: {Task(<acquire>)<PENDING>}
after cancel: <asyncio.locks.Semaphore object at 0x1 [locked,waiters:1]> <asyncio.locks.Semaphore object at 0x2 [locked]>
after wait: <asyncio.locks.Semaphore object at 0x1 [unlocked,value:1]> <asyncio.locks.Semaphore object at 0x2 [locked]>