首页 新闻 会员 周边 捐助

分析以下 asyncio 代码片段,并预测其终端输出内容的正确顺序。

0
[已解决问题] 解决于 2025-11-27 17:49

import asyncio

async def my_task(name, delay):
    print(f"Task {name}: starting")
    await asyncio.sleep(delay)
    print(f"Task {name}: finished")
async def main():
    print("Main: creating tasks")
    task1 = asyncio.create_task(my_task("A"1))
    task2 = asyncio.create_task(my_task("B"0.5))
    print("Main: tasks created")
    await task1
    await task2
    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
*Tesla*的主页 *Tesla* | 小虾三级 | 园豆:1152
提问于:2025-11-27 17:46
< >
分享
最佳答案
0
正确答案: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 密集型场景优化
*Tesla* | 小虾三级 |园豆:1152 | 2025-11-27 17:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册