# 并发与异步编程 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
分别处理] ```