大家好,我是正在实战各种 AI 项目的程序员晚枫。
asyncio 让 Python 单线程处理数万并发连接成为可能。但很多人学 asyncio 总是感觉"懂了又没懂"——这是因为没有从事件循环的角度去理解它的本质。
本讲从底层原理出发,带你真正搞懂异步编程。
🔄 为什么需要异步?
传统同步代码中,IO 等待会阻塞整个线程:
1 | 同步模型(单线程): |
关键洞察:IO 等待期间,CPU 是空闲的。异步编程就是充分利用这段空闲时间。
🏗️ 核心概念:事件循环与协程
协程(Coroutine)
协程是可以暂停和恢复执行的函数:
1 | import asyncio |
事件循环(Event Loop)
事件循环是 asyncio 的核心调度器:
1 | import asyncio |
🚀 asyncio 核心 API
asyncio.gather:并发执行多个协程
1 | import asyncio |
asyncio.create_task:更细粒度的任务控制
1 | import asyncio |
asyncio.wait:等待部分完成
1 | import asyncio |
🌐 实战:高并发爬虫
1 | import asyncio |
🔒 异步同步原语
asyncio.Lock:异步锁
1 | import asyncio |
asyncio.Queue:生产者消费者
1 | import asyncio |
🔗 同步代码与异步代码的桥接
1 | import asyncio |
📊 多线程 vs asyncio 对比
| 对比维度 | 多线程(threading) | asyncio |
|---|---|---|
| 并发模型 | 抢占式(OS 调度) | 协作式(主动让出) |
| 内存开销 | 每个线程约 8MB 栈 | 协程极小(几 KB) |
| 适用规模 | 数百个线程 | 数万个协程 |
| 共享状态 | 需要 Lock(复杂) | 单线程,较少竞态 |
| 调试难度 | 竞态条件难排查 | 更可预测 |
| 生态支持 | 所有库都支持 | 需要 async 版本库 |
⚠️ 常见陷阱
1. 在协程中调用阻塞函数
1 | import asyncio |
2. 忘记 await
1 | async def main(): |
3. 在非 async 函数中调用 async 函数
1 | async def async_func(): |
🎯 本讲总结
事件循环:asyncio 的核心调度器,单线程中交替执行协程,靠协程主动 await 让出控制权。
协程 vs 线程:协程更轻量(万级并发)、更可预测(无竞态条件);但必须全栈 async,不能调用阻塞函数。
核心 API:
asyncio.run()—— 入口,运行顶层协程asyncio.gather()—— 并发执行,等待全部完成asyncio.create_task()—— 立即开始但不阻塞当前协程asyncio.Semaphore—— 限制并发数量
桥接同步代码:用 loop.run_in_executor() 在线程池中运行同步阻塞函数,避免阻塞事件循环。
选择原则:IO 密集且并发数高(>数百)→ asyncio;IO 密集并发适中 → 多线程也可以;有大量已有同步代码 → 多线程更容易迁移。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
学习路线: 零基础 → 《从入门到实践》 → 《流畅的 Python》 → 本门课程 → 《CPython 设计与实现》
🎓 加入《流畅的 Python》直播共读营
学到这里,如果你想系统吃透这本书——欢迎加入我的直播共读课。
- 每周直播精讲,逐章拆解核心知识点
- 专属学习群,随时答疑交流
- 试运营特惠:
499 元→ 299 元
👉 【立即报名《流畅的 Python》共读课】:https://mp.weixin.qq.com/s/ivHJwn1nNx5ug4TFrapvGg
🔗 课程导航
← 上一讲:并发编程模型 | 下一讲:性能优化 →
💬 联系我
| 平台 | 账号/链接 |
|---|---|
| 微信 | 扫码加好友 |
| B 站 | Python 自动化办公社区 |
主营业务:AI 编程培训、企业内训、技术咨询
