import asyncio
l = asyncio.Lock()
async def test():
print('locked' if l.locked() else 'unlocked')
await l.acquire()
# await asyncio.ensure_future(l.acquire())
await asyncio.sleep(1)
l.release()
async def main():
await asyncio.gather(test(), test())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
我们启动两个test()
协同程序,其中第一个立即锁定l.acquire()
锁定,第二个打印locked
状态。输出:
unlocked
locked
如果您要评论await l.acquire()
行并取消注释下一行,则所有内容都会发生变化。输出将是:
unlocked
unlocked
这是因为在l.acquire()
启动第二个test()
后,任务中包含l.acquire()
。
有没有办法让test()
任务在第二Function math(n As Integer) As Double
Math = ((n - 1) * 2 + 5) * Abs((n - 1) - (n = 1))
End Function
之前尽快启动(并获得与原始代码相同的输出)?
答案 0 :(得分:0)
看起来我找到了解决方案。我们需要全局锁定,以便在第一个任务开始时暂停第二个任务锁定检查:
import asyncio
l = asyncio.Lock()
check_lock = asyncio.Lock()
async def test():
async with check_lock:
print('locked' if l.locked() else 'unlocked')
await asyncio.ensure_future(l.acquire())
print('now', 'locked' if l.locked() else 'unlocked')
await asyncio.sleep(1)
l.release()
async def main():
await asyncio.gather(test(), test())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:
unlocked
now locked
locked
# 1 second delay here
now locked
但是在这里我们得到了另一个问题:第一个任务完全完成后,第二个任务将被暂停,这就是为什么我们在第二个锁定之前得到1秒的延迟。在原始示例中很难看到(因为test()
等待单锁),这就是我添加第二次打印的原因。但是multiple locking of different resources立即启动协程可能很重要:我们应该仅锁定创建任务,但不是等待它。创建任务本身不会立即启动该任务(和l.acquire()
),我们应该将控制权返回给事件循环。它可以由await asyncio.sleep(0)
完成。这是原始代码的最终解决方案:
import asyncio
l = asyncio.Lock()
check_lock = asyncio.Lock()
async def test():
async with check_lock:
print('locked' if l.locked() else 'unlocked')
task = asyncio.ensure_future(l.acquire()) # only create task
await asyncio.sleep(0) # return control to event loop, it allows lock to be locked before task completed
print('now', 'locked' if l.locked() else 'unlocked') # would be printed immediately
await task # and now we can await for task done
await asyncio.sleep(1)
l.release()
async def main():
await asyncio.gather(test(), test())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:
unlocked
now locked
locked
# no delay here
now locked