Python多线程在I/O密集型任务中可提升响应速度,但受GIL限制无法并行执行CPU密集型代码;常见错误包括主线程过早退出、传参带括号、未调用join()、忽略锁导致竞态;应正确使用Future、as_completed、合理设置max_workers,并依据场景选择Lock、Queue或multiprocessing。

Python 的多线程在 I/O 密集型任务中确实能提升响应速度,但受 GIL 限制,无法真正并行执行 CPU 密集型代码——这不是 bug,是设计取舍,得先认清楚这点再动手。
threading.Thread 启动线程时为什么函数不执行或立即退出
常见现象:调用 t.start() 后主线程结束,子线程被强制终止;或传参写成 target=my_func()(带括号),导致函数当场执行而非在线程中运行。
- 必须用
target=my_func(不带括号),参数通过args=()或kwargs={}传入 - 主线程若无阻塞,需显式调用
t.join()等待子线程完成,否则进程可能提前退出 - 避免在子线程中直接 print 或修改全局变量而不加锁——
threading.Lock不是可选,是必需
concurrent.futures.ThreadPoolExecutor 提交任务后结果拿不到或顺序错乱
使用 submit() 返回的是 Future 对象,不是函数返回值本身;map() 虽方便,但会按输入顺序阻塞等待全部完成,丢失并发优势。
- 要获取结果,必须调用
future.result(),它会阻塞直到该任务完成 - 想保持提交顺序但不阻塞,可用
as_completed([f1, f2, f3])迭代最先完成的Future -
max_workers设太大(如 100+)反而因线程切换开销降低性能,I/O 密集建议设为 CPU 核数 × 4~5,实测更稳
线程间共享数据时出现竞态条件但没报错
竞态不是每次都会暴露,它依赖线程调度时机,所以“偶尔出错”才是最危险的信号。比如两个线程同时对 counter += 1 操作,底层其实是读-改-写三步,中间可能被打断。
立即学习“Python免费学习笔记(深入)”;
- 不要依赖
threading.local()来“绕过”同步——它是线程局部存储,解决的是数据隔离,不是共享安全 - 对简单计数/状态更新,优先用
threading.Lock;对更复杂状态,考虑queue.Queue做线程安全通信 - 注意:
list.append()和dict[key] = value在 CPython 中是原子操作,但counter += 1、list.extend()、dict.update()都不是
真正难的从来不是怎么开线程,而是判断哪里该加锁、哪里该用队列、哪里其实该换 multiprocessing——GIL 是背景音,不是挡箭牌。



















