You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何asyncio队列的await queue.get()会阻塞?代码执行顺序疑问

为什么先调用consumer()再调用producer()时asyncio队列会阻塞?

咱们先看你给出的两种场景:

阻塞的代码场景

import asyncio
async def producer(queue, item):
    await queue.put(item)
async def consumer(queue):
    val = await queue.get()
    print("val = %d" % val)
async def main():
    queue = asyncio.Queue()
    await consumer(queue)
    await producer(queue, 1)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

正常运行的代码场景

async def main():
    queue = asyncio.Queue()
    await producer(queue, 1)
    await consumer(queue)

你的疑问是:为什么await queue.get()没有把控制权交还给事件循环,让producer协程运行填充队列?


其实问题的核心不是queue.get()没交还控制权,而是main协程的执行顺序限制了producer的启动时机,咱们一步步拆解:

  1. 在阻塞场景的main里,你是顺序await的:先执行await consumer(queue),这会让main协程暂停,直到consumer协程完全执行完毕,才会去执行下一行的await producer(queue,1)。
  2. 当consumer协程启动后,遇到await queue.get()——因为队列是空的,consumer会暂停并把控制权交还给事件循环。但这时候事件循环里,只有main协程在等着consumer结束,producer还没被创建和调度呢!毕竟main要等consumer跑完才会去调用producer。
  3. 事件循环里没有其他可运行的协程,只能一直等着consumer的queue.get()拿到数据,但永远等不到——因为producer根本没机会启动往队列里放数据,这就造成了阻塞。

打个比方:你让家人先去快递站拿快递,但你要等家人拿到快递回来,才会联系快递员发快递,这不就卡死了嘛!

而反过来的正常场景里,你先让producer把数据放进队列,再让consumer去拿,自然顺理成章,不会有问题。


怎么让先consumer再producer也正常运行?

如果想让consumer和producer同时运行,不能用顺序await,得让它们并发执行,比如用asyncio.gather():

async def main():
    queue = asyncio.Queue()
    await asyncio.gather(
        consumer(queue),
        producer(queue, 1)
    )

这样事件循环会同时调度两个协程:consumer卡在queue.get()时,producer会被执行并把数据放进队列,consumer拿到数据后继续执行,程序就能正常结束了。

内容的提问来源于stack exchange,提问作者Akshay Takkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:53:01