Python多线程对CPU密集型任务几乎无加速效果,仅IO密集型任务受益;内置类型单方法看似原子,但复合操作(如if not in后赋值、counter += 1)非原子,易致竞态条件。
Python多线程不是“开多个线程就能加速”,关键在是否线程安全。由于全局解释器锁(GIL)的存在,CPU密集型任务用多线程几乎不提速,而IO密集型任务才真正受益;更关键的是,多个线程同时读写共享数据时,极易出现竞态条件——这不是bug,是没做同步的必然结果。
Python中大多数内置类型(如 list、dict、set)的单个方法看似原子,但复合操作(如 if key not in d: d[key] = value)绝非原子。哪怕只是 counter += 1,背后也包含读取、计算、写入三步,线程可能在任意一步被切换,导致丢失更新。
if 'x' not in d: d['x'] = 0 可能被两个线程同时通过判断,最终只写入
一次if len(lst) 同样存在检查与动作分离的问题
threading.Lock 是最基础也最常用的同步原语。它不阻止线程运行,只确保同一时刻最多一个线程能进入被它保护的代码块(临界区)。注意:Lock必须成对使用(acquire / release),推荐用 with 语句自动管理,避免忘记释放导致死锁。
with lock: shared_list.append(x)
lock.acquire(); shared_list.append(x); # 忘记lock.release()
不必所有场景都手写锁。Python标准库提供了专为多线程设计的类型,它们内部已封装同步逻辑,更简洁可靠:
立即学习“Python免费学习笔记(深入)”;
put() 和 get() 自动加锁,还支持阻塞、超时、任务完成通知(task_done() / join())Thread 更高层,自动管理线程生命周期、异常传播和结果收集,配合 submit() + as_completed() 写法清晰不易出错不是所有并发需求都适合 threading。遇到以下情况,应主动换方案:
线程安全不是靠经验猜出来的,而是靠明确识别共享状态、划定临界区、选择合适同步机制来保证的。写多线程代码前,先问自己:哪些变量会被多个线程访问?哪些操作必须原子?有没有更安全的替代方案?想清楚这三点,就踩对了第一步。