2. 进程&线程&协程到底是啥? python Flask 与Fastapi对比

49 阅读4分钟

1. 进程(Process)—— 独立的厨房

比喻:多个厨房,各自独立工作,每个厨房里有自己的厨师团队,互不干涉。

  • 进程是操作系统分配资源的基本单位,每个进程有独立的内存,互不影响。
  • 进程间通信(IPC)成本较高,比如需要用管道、消息队列等方式。

例子:

你开了一个连锁餐厅,有 4 个独立的厨房(相当于 4 个进程)。

  • 每个厨房完全独立,有自己的食材(内存)和厨师(CPU 资源)。
  • 客人(请求)来了之后,会被分配到某个厨房,厨房做好菜再送出去。
  • 厨房之间不会共享食材(进程间不共享内存)。
  • 但如果客人需要从两个厨房点菜,就要用**对讲机(进程间通信 IPC)**沟通。

2. 线程(Thread)—— 厨房里的多位厨师

比喻:一个厨房里有多个厨师,他们可以同时炒菜,但共用同一个冰箱、调料架(共享内存)。

  • 线程是CPU 调度的基本单位,一个进程可以有多个线程,线程共享内存
  • 线程之间可以快速通信,但如果多个线程同时修改共享资源(比如冰箱里的食材),可能会发生数据竞争(race condition) ,需要加锁(比如 GIL 在 Python 里限制了真正的并行)。

例子:

  • 你有 1 个厨房(1 个进程),但里面安排了4 个厨师(4 个线程)
  • 这些厨师共用同一个冰箱、调料架(共享数据)。
  • 这样,一个厨师可以炒菜,另一个厨师可以炸鸡,同时进行(并发)。
  • 但如果两个厨师同时想拿盐,就可能会发生冲突,这时候需要一个"规则"来管理谁先用(类似于加锁 Mutex)。

实际应用:

  • 在 Flask 里,用 Gunicorn + threads 让多个请求同时被不同线程处理。
  • 但 Python 里有 GIL(全局解释器锁),所以线程并不能真正利用多个 CPU 核心(更多用于 I/O 密集任务)。

3. 协程(Coroutine)—— 一个厨师能同时做多个菜

比喻:一个超级厨师,一边煮汤,一边炒菜,汤炖着的时候,顺便去切菜。

  • 协程是一种用户态的"轻量级线程" ,本质上是单线程,但可以在等待 I/O 的时候主动切换任务,从而提高效率(异步 I/O)。
  • 协程不需要操作系统的调度,切换速度比线程快很多,也不会有线程锁的问题。

例子:

  • 你只有 1 个厨师(单线程) ,但这个厨师很聪明,他会在炖汤的时候去炒菜,在等水烧开的空闲时间去切菜
  • 这样,他能在短时间内处理多个订单,即使他是一个人
  • 但如果一个任务(比如煎牛排)不能被打断,就会卡住整个流程(类似于同步代码中的阻塞操作)。

实际应用:

  • FastAPI 里,async / await 允许 API 在等待数据库查询或 HTTP 请求时,不阻塞其他请求,提高并发能力。
  • 适用于I/O 密集型任务(如数据库查询、网络请求)。
  • 不适用于 CPU 密集型任务,因为它还是单线程的。

总结

类型例子适用场景优势劣势
进程独立厨房,各做各的适合 CPU 密集任务(多进程)真正的并行执行,能用多核 CPU进程切换成本高,通信困难
线程一个厨房,多位厨师同时做菜适合 I/O 密集任务(多线程)线程间通信快,共享内存需要加锁,Python 受 GIL 限制
协程一个厨师,同时做多道菜适合 I/O 密集任务(异步 IO)切换开销低,不需要锁不能利用多核 CPU,遇到 CPU 密集型任务就会卡住

Flask 默认是同步的 用默认的 app.run(),那就是单进程 + 单线程,并发能力很低。(需要 Gunicorn + 线程/进程支持并发)。
FastAPI 天生支持协程async / await),可以在单线程下高效处理并发请求。 FastAPI 之所以高并发,核心就是基于 Python 的 asyncawait,实现了协程并发处理请求。

  • 当遇到 I/O 操作(比如数据库查询、HTTP 请求)时,FastAPI 不会阻塞线程,而是让出 CPU,去处理其他请求。

  • 这和传统的多线程、进程不同,是单线程的异步并发

你应该选择哪种方式?

  1. I/O 密集型(数据库、HTTP 请求)FastAPI + Uvicorn(协程)
  2. CPU 密集型(数据处理、加密计算)多进程(Gunicorn / Celery 任务队列)
  3. 同时涉及 I/O 和 CPU 任务FastAPI + Celery(任务队列)

你现在的 Flask 项目如果想提高并发能力,考虑:

  • 多线程(适用于 Flask 但受 GIL 限制)
  • 异步(迁移到 FastAPI,用 async 处理 I/O)
  • 多进程(适用于 CPU 密集型任务)
  • 任务队列(Celery 处理后台任务)