多线程适合I/O密集型任务,因等待时释放GIL;CPU密集型任务应选多进程以绕过GIL;异步编程需配合线程池或进程池处理阻塞操作;共享资源必须用锁等机制显式同步。

多线程适合I/O密集型任务,但受GIL限制
CPython解释器存在全局解释器锁(GIL),导致同一时刻只有一个线程执行Python字节码。这意味着CPU密集型任务用多线程无法真正并行,性能提升有限甚至更慢。但对网络请求、文件读写、数据库查询等I/O操作,线程在等待时会主动释放GIL,让其他线程运行,此时多线程能显著提升吞吐量。
建议:用 threading 或 concurrent.futures.ThreadPoolExecutor 管理线程池。控制最大线程数(如 10–20),避免创建过多线程引发上下文切换开销或系统资源耗尽。例如并发抓取100个网页,设 max_workers=15 通常比盲目开100个线程更稳定高效。
多进程绕过GIL,真正并行处理CPU密集任务
每个进程拥有独立内存空间和Python解释器,不受GIL约束,适合图像处理、数值计算、加密解密等CPU-heavy场景。但进程启动开销大、内存占用高、进程间通信(IPC)比线程间共享变量复杂。
建议:
• 用 multiprocessing 模块或 concurrent.futures.ProcessPoolExecutor
• 避免在子进程中直接引用不可序列化的对象(如lambda、嵌套函数、某些类实例),否则会报 PicklingError
• 大数据传递优先用 multiprocessing.Manager、Queue 或共享内存(multiprocessing.Array/Value),而非全局变量
异步任务调度推荐使用 asyncio + ThreadPoolExecutor/ProcessPoolExecutor
纯 asyncio 适合高并发I/O(如万级HTTP长连接),但无法直接运行阻塞调用(如 time.sleep()、requests.get())。正确做法是把同步阻塞操作“外包”给线程池或进程池,用 loop.run_in_executor() 调度:
立即学习“Python免费学习笔记(深入)”;
await loop.run_in_executor(pool, blocking_func, *args)
• I/O阻塞函数 → 交给 ThreadPoolExecutor
• CPU阻塞函数 → 交给 ProcessPoolExecutor
这样既保持async代码结构清晰,又规避了GIL和阻塞问题。实际项目中常见混合模式:主协程调度,I/O走线程池,计算走进程池。
竞态条件必须显式控制,不能依赖“看起来安全”
多线程/多进程共享资源(如全局计数器、文件、数据库记录)时,读-改-写操作极易出错。例如 counter += 1 实际分三步:读值→计算→写回,中间可能被其他线程打断。
解决方式按场景选择:
• 线程内:用 threading.Lock 或 threading.RLock 包裹临界区
• 进程间:用 multiprocessing.Lock,或通过 Manager().Value() + 锁配合
• 更高阶需求:用 threading.Condition 实现等待通知,或 queue.Queue 替代手动共享列表(它内部已加锁)
• 数据库操作:靠事务隔离级别(如READ COMMITTED)+ 行级锁(SELECT ... FOR UPDATE)保障一致性,不要在线程里自己“查再改”










