Asyncio事件循环结束时仅完成首个waiter任务的技术原因
问题分析与解答
核心原因分为两点:
事件循环的终止逻辑:
asyncio.run(main())仅会等待传入的main协程执行完毕,之后立刻启动事件循环的关闭流程。关闭时会取消所有未完成的后台任务(包括通过asyncio.create_task创建的任务),不会等待这些任务自然结束。锁等待与任务调度的时序:
main先调用lock.acquire()获取锁,随后创建的waiter和waiter2任务在执行async with lock时,因锁已被持有而挂起,进入锁的FIFO等待队列(waiter先创建,排在队列最前面)。main睡眠2秒后释放锁,此时队列最前面的waiter任务变为就绪状态,但由于main接下来执行的是同步代码(打印released),没有触发协程切换,waiter无法立即执行。main执行完毕后,事件循环在关闭前会先处理已就绪的waiter任务:waiter获取锁并打印... got it!,随后释放锁。此时waiter2才变为就绪状态,但事件循环已经进入关闭阶段,不会再调度执行该任务,直接将其取消,因此看不到2 ... got it!的输出。
补充:代码中 waiter_task 被重复赋值,导致第一个任务的引用丢失,但这不是 waiter2 未执行的原因——事件循环仍会跟踪该任务,只是无法通过变量手动等待它。
内容的提问来源于stack exchange,提问作者Kryptic Coconut
相关产品推荐
相关产品推荐

