Python线程同步主要靠Lock和Condition:Lock用于互斥访问临界区,需成对使用且避免嵌套死锁;Condition用于线程间等待通知,必须配合while循环检查条件,notify前须先修改条件。

Python中线程同步主要靠threading模块提供的原语实现,锁(Lock)和条件变量(Condition)是最常用、也最易出错的两种机制。正确使用它们的关键在于:明确共享资源边界、严格配对加锁/解锁、避免死锁与虚假唤醒。
锁(Lock):保护临界区的基本手段
锁用于确保同一时刻只有一个线程能执行某段代码(即“临界区”)。它不关心状态,只提供互斥访问。
- 创建后默认处于“未锁定”状态,调用
.acquire()阻塞获取,.release()释放;必须成对出现,否则其他线程永久等待 - 推荐用
with lock:语法,自动处理异常下的释放,避免忘记release() - 不要在持有锁时做耗时操作(如I/O、sleep、网络请求),否则严重拖慢并发效率
- 多个锁嵌套时,务必按固定顺序获取(如总先lock_a再lock_b),否则极易引发死锁
条件变量(Condition):协调线程间等待与通知
条件变量本质是“带唤醒机制的锁”,适用于一个或多个线程需等待某个条件成立(如队列非空、缓冲区有数据)后再继续执行的场景。
- 必须关联一个
Lock(可显式传入,也可默认新建),所有wait()/notify()操作都隐含锁的释放与重获 -
wait()会原子性地释放锁并挂起当前线程,被notify()或notify_all()唤醒后,会重新尝试获取锁,再返回 —— 因此wait()后必须重新检查条件是否真正满足(用while而非if) -
notify()只唤醒一个等待线程,notify_all()唤醒全部;若无等待线程,通知会被忽略(不会积压) - 典型模式:
with cond: while not condition_met: cond.wait(),然后处理逻辑
锁 vs 条件变量:何时选哪个?
简单互斥访问(如更新全局计数器、写入共享字典)用Lock足够;需要“等某件事发生”再继续(如生产者-消费者模型中消费者等数据、主线程等子线程完成)则必须用Condition。
立即学习“Python免费学习笔记(深入)”;
-
Lock适合“禁止同时进入”,Condition适合“允许进入但需满足前提” -
Event也可用于简单通知,但它是一次性信号且不带锁,无法替代Condition在复杂同步中的作用 - 过度依赖
time.sleep()轮询判断条件,不仅低效还可能漏事件,应优先用Condition代替
常见错误与避坑提示
很多同步问题不是逻辑错,而是使用姿势不对。
- 在
Condition.wait()外修改被等待的条件变量,且未加锁 —— 导致竞争和条件检查失效 - 用
if判断条件后wait(),而非while—— 可能因虚假唤醒或条件被其他线程改回而直接出错 - 忘记在
notify()前修改条件本身(如往队列put后才notify),导致唤醒了却仍不满足条件 - 多个线程共用同一个
Condition但等待不同条件,却混用notify()—— 应考虑拆分或用更细粒度的通知逻辑










