文章
合集Python 并发编程第 1 / 7 篇

并发概论:选型与决策

这是并发编程系列的总览篇。读完这篇文章,你会知道"我这任务该用什么方案"。后续每篇文章解决一个具体武器的使用细节。

1. 核心概念辨析

概念一句话生活类比
并发(Concurrency)多个任务交替执行,看起来同时一个人在两个菜锅间来回翻炒
并行(Parallelism)多个任务真正同时执行两个人各炒一个锅
同步(Synchronous)调用后阻塞等待结果再继续点餐后站在柜台等,饭好了才走
异步(Asynchronous)调用后立即返回,结果通过回调或 await 获取点餐后拿号坐下,好了叫号
阻塞(Blocking)当前线程停止等待某个操作完成水龙头开着,你站在那儿等水烧开
非阻塞(Non-blocking)操作未就绪时立即返回,不等待水龙头开着,你先去切菜

2. I/O 密集 vs CPU 密集

这是决定选型的关键分类。

2.1 什么是 I/O 密集

大部分时间在等——等网络响应、等磁盘读写、等数据库返回。

常见例子:
- HTTP 请求 / 爬虫
- 文件读写(尤其是大文件)
- 数据库查询
- 调用外部 API(LLM、支付网关)

特点:CPU 大部分时间空闲,瓶颈在网络或磁盘延迟。

2.2 什么是 CPU 密集

大部分时间在算——数学计算、压缩、加密、图像处理、机器学习推理。

常见例子:
- 图片压缩 / 缩放
- 数据分析(pandas 聚合)
- 加密解密(hash、AES)
- 科学计算(矩阵运算)

特点:CPU 一直跑满,瓶颈在计算能力。

2.3 怎么判断

经验法:把任务跑一遍,看 CPU 占用率——

  • 接近 100%:CPU 密集
  • 远低于 100%:I/O 密集

直觉法:代码里有 sleep、网络请求、文件读写?大概率 I/O 密集。全是数学运算和循环?大概率 CPU 密集。

3. GIL:Python 多线程的"原罪"

3.1 GIL 是什么

GIL(Global Interpreter Lock)——全局解释器锁。CPython 解释器内部的一把锁,同一时刻只允许一个线程执行 Python 字节码。

3.2 为什么存在

Python 的内存管理(引用计数、垃圾回收)不是线程安全的。GIL 是最简单的解决方案:用一把大锁保护整个解释器,避免并发修改导致内存错误。

3.3 影响是什么

场景GIL 的影响
CPU 密集 + 多线程多个线程抢 GIL,反而可能比单线程更慢
I/O 密集 + 多线程线程在等 I/O 时自动释放 GIL,其他线程能跑,有用

3.4 记忆口诀

I/O 密集 → 多线程或异步(GIL 不是问题,因为等 I/O 时会释放)
CPU 密集 → 多进程(绕开 GIL,每个进程有独立解释器)

Python 3.13 开始有实验性的"无 GIL"版本(PEP 703),但生产代码 5 年内还是按上面规则选。

4. Python 三种并发模型

模型模块适合场景切换开销最大并发量
多线程threadingI/O 密集(少量任务)低(KB 级内存)数千
多进程multiprocessingCPU 密集高(MB 级内存)CPU 核心数
异步asyncioI/O 密集(高并发)极低(用户态切换)数万

补充:concurrent.futures

Python 3.2 引入的统一接口,封装了多线程和多进程:

# 多线程
from concurrent.futures import ThreadPoolExecutor

# 多进程
from concurrent.futures import ProcessPoolExecutor

# 两者 API 完全一致——改一个类名就能切换方案

这是现代 Python 的首选并发 API,后续文章会重点讲解。

5. 选型决策树

这是本文的核心,也是整个系列的地图。

你的任务是 I/O 密集还是 CPU 密集?
│
├─ I/O 密集
│   ├─ 任务数少(< 100)→ ThreadPoolExecutor
│   └─ 任务数多(> 100)→ asyncio + 异步库
│
├─ CPU 密集
│   └─ ProcessPoolExecutor
│
└─ 调用外部命令(pandoc / ffmpeg / git)
    └─ subprocess.run

更细化的决策:

场景推荐方案原因
几个 API 调用ThreadPoolExecutor简单,够用
几百个爬虫请求asyncio + aiohttp高并发,低开销
图片批量压缩ProcessPoolExecutorCPU 密集,需要多核
调用 pandoc / ffmpegsubprocess.run外部命令,标准接口
混合任务(先拉数据再处理)asyncio + run_in_executor异步拉数据,线程池处理

6. 和现有内容的关系

文件定位关系
Python 进阶/并发与异步API 速查手册保留,不修改。新文章侧重原理讲解和实战
本系列(00-05)原理 + 实战教程从概念到代码,每个武器一篇

如果你已经读过 并发与异步.md,那篇是"查 API"用的;这个系列是"理解原理 + 学会选型"用的。互为补充。

7. 各篇导航

篇目内容适合你想学的
python-multithreadingthreading + Lock + ThreadPoolExecutor"我想用多线程但不知道怎么用"
python-multiprocessingmultiprocessing + IPC + ProcessPoolExecutor"CPU 密集任务怎么加速"
python-asyncio协程 + 事件循环 + 异步生态"我想学 asyncio"
python-subprocesssubprocess.run 工业级模板"怎么从 Python 调外部命令"
python-concurrent-llm-calls综合案例,贯穿所有知识点"给我一个完整的实战例子"