线程和进程
1. 线程 vs 进程
| 进程 Process | 线程 Thread | |
|---|---|---|
| 定义 | 操作系统分配资源的单位 | 进程内的执行流,CPU 调度的单位 |
| 拥有 | 独立内存、文件、权限、环境变量 | 只独占栈和寄存器 |
| 内存 | 各进程互相隔离 | 同进程内所有线程共享 |
| 成本 | 创建/切换毫秒级,重 | 创建/切换微秒级,轻 |
| 数量关系 | 一个进程 ≥ 1 个线程 | 线程必须属于某个进程 |
进程
├── 内存 / 文件 / 权限 ← 进程"拥有"的
└── 线程 × N ← 线程"执行"的
一句话:进程管「有什么」,线程管「干什么」。进程崩了线程全灭;线程崩了进程没事。
2. 并发 vs 并行
| 并发 Concurrency | 并行 Parallelism | |
|---|---|---|
| 定义 | 多个任务交替推进,任一时刻只有 1 个在跑 | 多个任务同时推进,任一时刻有 N 个在跑 |
| 前提 | 不需要多核 | 必须有多核 |
| 判定 | CPU时间 ÷ 墙钟时间 ≈ 1 | CPU时间 ÷ 墙钟时间 ≈ N |
| 本质 | 关于结构 | 关于硬件 |
并发(1核) 并行(3核)
时刻: 0 1 2 3 时刻: 0 1 2 3
核0 A B A C 核0 A A A A
核1 · · · · 核1 B B B B
核2 · · · · 核2 C C C C
一句话:并发是”看起来同时”,并行是”真的同时”。
3. 四者的关系
它们是两个正交维度:
- 线程/进程 = 容器(谁干活、共享什么)
- 并发/并行 = 时间轴排列(交替还是同时)
并发(交替) 并行(同时)
线程 ✅ 默认如此 ⚠️ 仅当代码释放 GIL
(如 NumPy;纯 Python 被 GIL 锁死)
进程 ✅ 当然可以 ✅ 天然如此(每个进程独占一核)
协程 ✅ 只能这样 ❌ 单线程,永远不并行
GIL是python的Global Intepreter Lock,让一个进程内的所有线程共用一个执行单元,所以 Python 多线程排不成横队,只能排纵队。 也就是说在python里面除非多线程任务能释放GIL(NumPy、PyTorch……),这样线程任务也可以放到多个核上面跑。否则,通过多线程只能在单核上跑实现并发,无法实现并行计算。
4. 并行好理解,那并发有啥好处吗
python代码执行默认是串行的。
代码:step('A', 0.3); step('B', 0.3); step('C', 0.3)
(最普通的写法,没有任何 threading)
A |################## |
B | ################# |
C | ###################|
+------------------------------------------------------+
0 0.90s
总耗时 0.90s = 0.3 + 0.3 + 0.3
三个条形【首尾相接,毫无重叠】
B 必须等 A 执行完才轮到它,C必须等到B执行完后才执行。
Python 代码默认严格串行,一行执行完才走下一行。 但 NumPy 这类 C 扩展库会在内部并行——你的代码串行,库帮你并行。
并发比起串行,好处就一个,就是当你的任务存在等待的时候,并发可以减少等待时间。
任何一个真实任务都能拆成:
- [计算段] CPU 真的在干活 —— 解析数据、算数、拼字符串
- [等待段] CPU 闲着,任务在原地等 —— 等网络返回、等磁盘读完、等数据库响应
关键在于:等待段里 CPU 是完全闲置的。 它没在忙别的,就是在干等。
A |###............ |
B | ####............ |
C | ####............. |
D | ###............ |
|###------------####------------####-------------###-------------| ← CPU
+----------------------------------------------------------------+
0 2.08s
# = 计算段(CPU 忙) . = 等待段(CPU 闲着) - = CPU 完全空闲
CPU 实际忙碌占比 23%
使用并发可以在某个任务等的时候做另一个任务
A |###########.................................... |
B | ############.................................... |
C | ############.................................... |
D | ###########.................................... |
|###########################-------------------------------------| ← CPU
+----------------------------------------------------------------+
0 0.71s
CPU 实际忙碌占比 69%
生活类比:一个人做饭
串行:
烧水 5 分钟 —— 站在灶台边盯着看
水开了,切菜 3 分钟
一共 8 分钟,出一道菜
并发:
烧上水,转身去切菜(3 分钟)
水开了,菜也切好了,下锅
一共 5 分钟,出两道菜
你没有变快。 你还是那个只有一个身体的厨师。你只是不再站着看了。
5. 总结和建议
操作系统
└── 进程(资源隔离,真实并行)
└── 线程(OS 调度,受 GIL 限制 → 同进程内只能并发)
└── 协程(Python 事件循环调度,OS 看不见)
CPU 密集 → 往【上】走,用进程抢多核
I/O 密集 → 往【下】走,用协程/线程重叠等待
数值计算 → 跳出这套,直接用 NumPy
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Comments




