五种并发/异步模型整理
五种并发/异步模型整理
1. 线程(Thread)
- 理解:来一个任务开一个线程,独立运行。
- 特点:抢占式调度,内核管理,阻塞不影响主线程。
- 优点:简单、逻辑像同步一样顺。
- 缺点:重、耗资源、多锁容易死锁。
- 场景:普通后台任务、少量并发。
2. 协程(Coroutine)
- 理解 :多个函数协同运行、互相让出、交替前进,一起推进状态。
- 特点:用户态切换,不阻塞线程,遇到等待主动 yield。
- 优点:极轻量、高并发、无内核开销。
- 缺点:需要手动或调度器切换。
- 场景:高并发网络、游戏逻辑、生产者消费者。
3. IO 多路复用(epoll / select / poll)
- 理解 :一个线程等待一堆 socket,哪个就绪处理哪个。
- 底层 :依赖网卡中断,内核标记就绪,epoll 只负责查询就绪集合。
- 优点:超高并发、极省资源。
- 缺点:编码是事件驱动,逻辑较绕。
- 场景:Nginx、Redis、高并发服务器。
4. 异步 IO(AIO)
- 理解 :提交读写请求就立刻返回,完成后系统主动通知。
- 底层 :完全依赖磁盘/网卡硬件中断。
- 优点:真正不阻塞,不轮询。
- 缺点:API 复杂,系统兼容性一般。
- 场景:高性能文件读写、存储系统。
5. 信号 + 回调
- 理解:内核通过信号通知进程,进程执行回调。
- 底层 :来自中断/异常的封装。
- 为什么不稳定 :
- 同一信号多次会合并丢失
- 没有队列,不适合高频
- 回调上下文不安全
- 场景:简单通知、超时、程序退出。
总结
- 线程:开小弟干活
- 协程:互相配合协同跑
- epoll:等一堆 IO 就绪
- AIO:提交完等中断通知
- 信号:中断封装的简单通知,但会丢、不稳定
5 种并发/异步模型 · 极简对比表
| 方式 |
核心一句话 |
底层靠什么 |
优点 |
缺点 |
典型场景 |
| 线程 |
一人一事,阻塞也各玩各的 |
内核调度 |
简单直观 |
重、耗资源、易死锁 |
普通后台任务、低并发 |
| 协程 |
多函数协同交替,一起推进 |
用户态切换 |
极轻量、高并发 |
需手动/调度器切换 |
高并发网络、游戏 |
| IO多路复用(epoll) |
一个线程等一堆IO,就绪才处理 |
网卡中断+内核就绪队列 |
超高并发、省资源 |
逻辑碎片化、事件驱动 |
Nginx、Redis、高并发网络通信服务 |
| 异步IO(AIO) |
提交IO就走,完成中断通知 |
磁盘/网卡硬件中断 |
真正不阻塞 |
API复杂、兼容性一般 |
高性能文件/存储读写 |
| 信号+回调 |
中断封装的简单通知 |
中断/异常 |
轻、简单 |
会丢信号、不安全、不可靠 |
闹钟、程序退出、简单通知 |
超短记忆版
- 线程:多个人独立干活
- 协程:互相让位协同干活
- epoll:一个人盯一堆事件
- AIO:提交完等硬件喊完成
- 信号:简易通知,但会丢