# 并发与异步编程
Python 提供了多种并发编程模型,理解它们的特点和适用场景是写出高效程序的关键。
```{toctree}
:maxdepth: 2
gil
threading
multiprocessing
asyncio
patterns
```
## 并发 vs 并行
```{mermaid}
graph TD
A[并发编程] --> B[并发 Concurrency]
A --> C[并行 Parallelism]
B --> D[单核心
任务交替执行]
C --> E[多核心
任务同时执行]
D --> F[线程/协程]
E --> G[多进程]
```
### 概念区分
| 特性 | 并发 (Concurrency) | 并行 (Parallelism) |
|------|-------------------|-------------------|
| 定义 | 同时处理多个任务 | 同时执行多个任务 |
| CPU | 可以是单核 | 需要多核 |
| Python 实现 | 线程、协程 | 多进程 |
| 适用场景 | I/O 密集型 | CPU 密集型 |
### Python 并发模型选择
```python
# 场景分析
# 1. I/O 密集型(网络请求、文件操作、数据库查询)
# 推荐:asyncio(首选)或 threading
# 原因:等待 I/O 时可以切换到其他任务
# 2. CPU 密集型(数值计算、图像处理、数据分析)
# 推荐:multiprocessing 或 concurrent.futures.ProcessPoolExecutor
# 原因:绕过 GIL,利用多核
# 3. 混合型
# 推荐:组合使用,或使用 Ray、Dask 等框架
```
## 快速对比
```python
import time
import threading
import multiprocessing
import asyncio
def io_bound_task():
"""I/O 密集型任务"""
time.sleep(1)
return "done"
def cpu_bound_task(n):
"""CPU 密集型任务"""
total = 0
for i in range(n):
total += i * i
return total
async def async_io_task():
"""异步 I/O 任务"""
await asyncio.sleep(1)
return "done"
# 测试代码...
```
### 性能对比(10 个 I/O 任务)
| 方式 | 时间 | 说明 |
|-----|------|------|
| 串行 | ~10s | 一个接一个 |
| 多线程 | ~1s | 并发执行 |
| 多进程 | ~1s | 并行执行(资源开销大)|
| asyncio | ~1s | 并发执行(最轻量)|
### 性能对比(CPU 密集型任务)
| 方式 | 时间 | 说明 |
|-----|------|------|
| 串行 | 基准 | - |
| 多线程 | ≈ 基准 | GIL 限制 |
| 多进程 | 基准/核心数 | 真正并行 |
| asyncio | ≈ 基准 | 不适合 CPU 密集 |
## 本章重点
::::{grid} 2
:gutter: 2
:::{grid-item-card} GIL 深度解析
理解全局解释器锁的原理和影响,知道何时它是问题,何时不是。
:::
:::{grid-item-card} 多线程编程
线程同步、锁、条件变量,以及如何避免死锁和竞态条件。
:::
:::{grid-item-card} 多进程编程
进程间通信、共享状态、进程池的正确使用。
:::
:::{grid-item-card} asyncio 异步编程
协程、事件循环、异步上下文,构建高性能异步应用。
:::
::::
## 选型指南
```{mermaid}
graph TD
A[任务类型?] --> B{I/O 密集型}
A --> C{CPU 密集型}
A --> D{混合型}
B --> E{需要高并发?}
E -->|是| F[asyncio]
E -->|否| G[threading]
C --> H{可以用 NumPy?}
H -->|是| I[NumPy 已释放 GIL]
H -->|否| J[multiprocessing]
D --> K[分离 I/O 和 CPU
分别处理]
```