asyncio.sleep(delay) VS time.sleep(delay)
·
核心结论
asyncio.sleep(delay) 是异步阻塞,不卡死事件循环;time.sleep(delay) 是同步阻塞,直接堵死整个事件循环,二者底层等待逻辑、对协程的影响完全不同。
一、基础对比
| 对比项 | asyncio.sleep(delay) |
time.sleep(delay) |
|---|---|---|
| 所属模块 | 异步库 asyncio |
标准同步库 time |
| 调用方式 | 必须搭配 await |
直接调用,不能加 await |
| 阻塞性质 | 协程级阻塞 | 线程级阻塞 |
| 执行时行为 | 协程挂起,释放事件循环线程,可调度其他协程 | 整条线程卡死,不释放执行权,事件循环停滞 |
| 适用场景 | 协程/异步代码内部 | 普通同步代码 |
二、逐点详解 + 代码演示
1. asyncio.sleep(异步休眠,协程友好)
import asyncio
async def task(name, t):
print(f"任务{name} 开始")
await asyncio.sleep(t) # 异步等待
print(f"任务{name} 结束")
async def main():
t1 = asyncio.create_task(task("A", 1))
t2 = asyncio.create_task(task("B", 2))
await t1
await t2
asyncio.run(main())
运行时序:
- A、B 先后启动;
- A 执行到
asyncio.sleep(1)→ 当前协程挂起,线程还给事件循环; - 循环切换执行 B;
- B 执行到
asyncio.sleep(2)→ 同样挂起; - 1秒后 A 唤醒执行收尾,2秒后 B 唤醒收尾;
总耗时 ≈ 2秒,正常并发。
本质:模拟异步IO等待,只是让出协程执行权,不占用线程,事件循环可以正常调度其他任务。
2. time.sleep(同步休眠,阻塞整个线程)
import asyncio
import time
async def task(name, t):
print(f"任务{name} 开始")
time.sleep(t) # 同步休眠
print(f"任务{name} 结束")
async def main():
t1 = asyncio.create_task(task("A", 1))
t2 = asyncio.create_task(task("B", 2))
await t1
await t2
asyncio.run(main())
运行时序:
- A 启动,执行
time.sleep(1)→ 整个事件循环线程被卡住; - 必须等1秒休眠结束,A 才会收尾;
- 之后才轮到 B 执行、休眠2秒;
总耗时 ≈ 3秒,完全退化成串行,并发失效。
本质:它是同步阻塞函数,会牢牢占用当前线程,不触发协程挂起、不释放执行权,事件循环无法切换任务。
三、关键补充知识点
-
语法限制
asyncio.sleep返回可等待对象,异步代码里必须写await,否则只是创建对象,不会等待;time.sleep是普通同步函数,不能加await,加了会报错。
-
异步代码中想用 time.sleep 怎么办?
用asyncio.to_thread把同步休眠丢到子线程执行,避免阻塞事件循环:# 安全写法 await asyncio.to_thread(time.sleep, 1) -
底层等待逻辑
两者最终都是调用操作系统内核完成“延时等待”,等待期间都不消耗CPU;
区别只在于:是否释放事件循环线程、是否允许任务切换。
四、使用选择
- 纯异步协程代码里做延时:优先用
await asyncio.sleep(),保证并发; - 同步代码、普通线程里做延时:用
time.sleep(); - 异步环境中必须调用
time.sleep/其他同步阻塞函数:套一层asyncio.to_thread。
一句话速记
asyncio.sleep 睡觉让出位置,别人可以干活;time.sleep 睡觉占着工位,所有人都得等着。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)