首页 问答 分析以下 asyncio 代码片段,并预测其终端输出内容的正确顺序。
问题详情

importasyncio

asyncdefmy_task(name,delay):
print(f"Task{name}:starting")
awaitasyncio.sleep(delay)
print(f"Task{name}:finished")
asyncdefmain():
print("Main:creatingtasks")
task1=asyncio.create_task(my_task("A",1))
task2=asyncio.create_task(my_task("B",0.5))
print("Main:taskscreated")
awaittask1
awaittask2
print("Main:finished")
asyncio.run(main())
A
Main: creating tasks → Main: tasks created → Task A: starting → Task B: starting → Task B: finished → Task A: finished → Main: finished
B
Main: creating tasks → Task A: starting → Task B: starting → Main: tasks created → Task B: finished → Task A: finished → Main: finished
C
Main: creating tasks → Main: tasks created → Task B: starting → Task A: starting → Task A: finished → Task B: finished → Main: finished
D
Main: creating tasks → Main: tasks created → Task A: starting → Task B: starting → Task A: finished → Task B: finished → Main: finished

回答

正确答案:A
官方解析:

– 先同步执行:Main: creating tasks → 创建两个任务 → Main: tasks created。
– await task1 时把控制权交回事件循环,两个任务开始运行,按创建顺序通常先打印 Task A: starting,再 Task B: starting。
– B 休眠 0.5s,A 休眠 1s,故先结束 B,再结束 A。
– task1 结束后继续 await task2(已结束),最后 Main: finished。

事件循环是一个无限循环,它等待并分发事件,协调所有异步操作的执行顺序。

想象一个餐厅经理(事件循环):

顾客(协程)点餐后不会一直站在厨房门口等待
顾客回到座位(挂起),经理记录订单(注册事件)
厨房做好菜(I/O 完成),经理通知对应顾客(恢复协程)
经理在等待期间可以服务其他顾客(并发处理)
没有空闲时间,所有资源都被高效利用
asyncio 事件循环本身运行在单线程中,但 asyncio 可以与多线程协同工作,形成混合架构
事件循环 = 单线程引擎

所有协程在同一个线程中执行
通过 await 点实现协作式多任务
任何时候只有一个协程”活跃”(占用CPU)
没有线程切换开销,没有锁竞争,没有竞态条件
事件循环始终运行在 MainThread
上面代码:代码中main线程有3个协程:main、task1(A)和task2(B)
main协程只在这一行真正让出控制权:await task1 ,此时main协程处于waiting状态,这行代码的字面意思是:”等待 task1 完成”

asyncio.create_task()只是将协程注册到事件循环,不会立即执行。当前协程(main)会继续执行直到遇到await

asyncio是协作式多任务,不是抢占式调度

main WAITING_FOR_TASK1 等待队列 在 await task1 处暂停
task1 READY 就绪队列 被 create_task 创建,可执行
task2 READY 就绪队列 被 create_task 创建,可执行
事件循环只会从就绪队列中选择协程执行,而 main 此时在等待队列中

await asyncio.sleep(1) 时:

✅ 不是阻塞:只是注册一个 1 秒后的定时器
✅ 主动让出:协程明确告诉事件循环”我现在不能继续”
✅ 精准调度:事件循环检查就绪队列,发现 task2 可以运行
✅ 零 CPU 浪费:在等待期间,线程完全休眠
✅ 确定性恢复:1 秒后精确恢复 task1,从 await 之后继续

这是协程,不是线程

  • 完全单线程:asyncio是基于单线程的协程模型,不是多线程
  • 协作式多任务:协程通过主动让出控制权(通过await)来实现并发,不像线程那样依赖操作系统的时间片调度
  • 没有CPU时间切片:asyncio的调度不是基于CPU时间片,而是基于I/O事件完成和显式的让出控制权

2. 事件循环和执行流程

  • 确定性的执行顺序:asyncio的执行顺序是确定的,不是随机的
  • main函数也是一个协程:它和其他任务一样由事件循环调度
  • await的真正含义:await task1不是将main加入等待队列,而是”挂起当前协程,直到task1完成,同时允许其他任务运行”
  1. CPU 密集型 vs I/O 密集型:

    • CPU 密集型任务:确实需要独占 CPU
    • I/O 密集型任务:99% 时间在等待 I/O,不占用 CPU
    • asyncio 专为 I/O 密集型场景优化

版权:言论仅代表个人观点,不代表官方立场。转载请注明出处:https://www.stntk.com/question/190.html

发表评论
暂无评论

还没有评论呢,快来抢沙发~

点击联系客服

在线时间:8:00-16:00

客服QQ

70068002

客服电话

400-888-8888

客服邮箱

70068002@qq.com

扫描二维码

关注微信公众号

扫描二维码

手机访问本站