进程 vs 线程 vs 协程 三者对比

一句话:进程是工厂,线程是工人,协程是工人的”分身术”。


一、从零开始:先搞懂”程序”是啥

 
程序 = 写好的代码(静态的,躺在硬盘上)
 
进程 = 跑起来的程序(动态的,占着内存和CPU)
 

类比:

  • 程序 = 菜谱(写在纸上,不会自己炒菜)

  • 进程 = 厨师正在炒菜(占着灶台、锅、食材)


二、三者定义——用工厂比喻

概念一句话定义工厂比喻
进程资源分配的最小单位,一个程序跑起来就是一个进程一个工厂(有厂房、设备、资金)
线程CPU调度的最小单位,进程里的执行单元工厂里的工人(共享工厂资源,各自干活)
协程用户态的轻量级线程,由程序自己调度工人的分身术(一个工人同时干多件事)

三、核心区别——一张表说清楚

维度进程线程协程
本质资源分配单位CPU调度单位用户态的”伪线程”
内存独立地址空间共享进程内存共享线程内存
创建开销大(要分配资源)中(共享资源)极小(只是函数调用)
切换开销大(涉及内核态)中(内核态切换)极小(用户态切换)
通信方式IPC(管道/共享内存等)直接读写共享变量直接读写(同线程)
数量通常几十个通常几百个可以几万个
崩溃影响一个崩了不影响其他一个崩了整个进程挂一个崩了影响线程

四、关系图——谁包含谁


graph TD

    A[进程 Process] --> B[线程 1]

    A --> C[线程 2]

    A --> D[线程 3]

    B --> E[协程 1.1]

    B --> F[协程 1.2]

    C --> G[协程 2.1]

    style A fill:#ff6b6b,color:#fff

    style B fill:#4ecdc4,color:#fff

    style C fill:#4ecdc4,color:#fff

    style D fill:#4ecdc4,color:#fff

    style E fill:#45b7d1,color:#fff

    style F fill:#45b7d1,color:#fff

    style G fill:#45b7d1,color:#fff

包含关系:进程 ≥ 线程 ≥ 协程


五、Python 特有:GIL 的影响

重点掌握:Python 有 GIL,多线程不能真正并行?

GIL 是什么?

 
GIL = Global Interpreter Lock(全局解释器锁)
 
同一时刻,只有一个线程能执行 Python 字节码
 

所以 Python 多线程是假的?

不完全对!

场景多线程有没有用?原因
CPU 密集型(计算)❌ 没用GIL 限制,只能轮流跑
IO 密集型(网络/文件)✅ 有用等IO时释放GIL,其他线程能跑
 
import threading
 
import time
 
# IO密集型:多线程有效
 
def io_task():
 
    time.sleep(1)  # 模拟IO,会释放GIL
 
# CPU密集型:多线程无效
 
def cpu_task():
 
    sum(range(10**7))  # 纯计算,不释放GIL
 

六、协程:Python 的”分身术”

为什么需要协程?

 
线程切换要进内核态 → 开销大
 
协程切换在用户态 → 开销极小
 

类比

场景线程协程
你同时看两本书两本书放桌上,眼睛来回切换一本书看5秒,自动跳另一本
厨师炒两个菜两个灶台,来回跑一个灶台,炒一会这个,炒一会那个

代码对比

 
# 线程版本
 
import threading
 
def task():
 
    time.sleep(1)
 
threads = [threading.Thread(target=task) for _ in range(100)]
 
# 协程版本
 
import asyncio
 
async def task():
 
    await asyncio.sleep(1)
 
tasks = [task() for _ in range(100)]
 
asyncio.run(asyncio.gather(*tasks))  # 极小开销
 

七、什么时候用什么?——选型决策树


graph TD

    A[你的任务是什么?] --> B{IO密集型?}

    B -->|是| C{需要高并发?}

    B -->|否| D{CPU密集型?}

    C -->|是 - 几千并发| E[协程 asyncio]

    C -->|否 - 几十个| F[线程 threading]

    D -->|是| G[多进程 multiprocessing]

    D -->|否| H[单线程就够了]

    style E fill:#45b7d1,color:#fff

    style F fill:#4ecdc4,color:#fff

    style G fill:#ff6b6b,color:#fff

    style H fill:#96ceb4,color:#fff


八、话术——直接背

Q1:进程和线程的区别?

进程是资源分配的最小单位,拥有独立的地址空间;线程是CPU调度的最小单位,共享进程的内存资源。创建进程开销大,创建线程开销小。进程间通信需要IPC机制,线程可以直接读写共享变量。

Q2:线程和协程的区别?

线程由操作系统调度,切换涉及内核态,开销较大;协程由用户程序自己调度,切换在用户态,开销极小。协程本质上是单线程内的并发,适合高并发IO场景。

Q3:Python 有GIL,多线程还有用吗?

对于IO密集型任务有用,因为等待IO时会释放GIL;对于CPU密集型任务没用,因为GIL限制了同一时刻只有一个线程执行字节码。CPU密集型应该用多进程。


九、实际项目中的应用

场景你的选择为什么
FastAPI 处理1000个并发请求协程IO密集,需要高并发
机器人同时处理多个用户消息协程IO密集(等LLM响应)
批量数据处理多进程CPU密集
简单脚本单线程没有并发需求

十、记忆口诀

 
进程重,线程轻,协程最轻巧
 
进程分资源,线程共享用
 
协程用户态,切换零开销
 
GIL 让线程排队走,IO场景协程牛
 

总结:进程管资源,线程管执行,协程管并发。Python 项目(特别是 FastAPI)默认用协程,CPU 密集用多进程,其他场景用线程。

速记卡(面试闪卡)

Q1:一句话讲清「进程 vs 线程 vs 协程 三者对比」到底是什么?

A:进程是资源分配单位、线程是 CPU 调度单位、协程是用户态轻量级线程,包含关系为进程≥线程≥协程。

Q2:一、从零开始:先搞懂”程序”是啥 —— 怎么理解?

A:像菜谱和厨师:程序(Program)是躺在硬盘上的静态代码像菜谱,进程(Process)是跑起来的程序像正在炒菜的厨师,占着灶台和食材。

Q3:二、三者定义——用工厂比喻 —— 怎么理解?

A:像工厂、工人和分身术:进程是一整个工厂(有厂房设备),线程是工厂里的工人(共享资源各干各的),协程是工人的分身术(一个工人同时干多件事)。

Q4:三、核心区别——一张表说清楚 —— 怎么理解?

A:像三种交通工具对比:进程创建开销大、独立内存;线程开销中等、共享内存;协程开销极小、用户态切换(User-mode Switching),数量可达几万。

Q5:四、关系图——谁包含谁 —— 怎么理解?

A:像套娃:包含关系是进程(Process)≥ 线程(Thread)≥ 协程(Coroutine),一个进程里可有多个线程,一个线程里可跑多个协程。

Q6:核心速记主线有哪些?

  • 进程是资源分配最小单位、有独立地址空间;线程是 CPU 调度最小单位、共享进程内存

  • 协程是用户态轻量级”伪线程”,切换在用户态、开销极小,可轻松跑到几万个

  • Python 有 GIL(Global Interpreter Lock,全局解释器锁),多线程 CPU 密集无效、IO 密集有用

  • 选型:IO 高并发用协程 asyncio,CPU 密集用多进程,简单场景用单线程

口诀

A:进程管资源线程管跑,协程最轻巧

工厂工人分身术,包含关系套娃牢

GIL 让线程排队走,IO 场景协程好

CPU 密集多进程,简单单线程就到

相关链接