python高级编程-condition
在 Python 的多线程编程中,threading.Condition(条件变量)是一个非常强大的线程同步工具。
你可以把它通俗地理解为 “高级版的 Event” 或者 “带锁的 Event”。
- Event 只能控制线程的“走”与“停”(红灯/绿灯)。
- Condition 则更精细,它允许线程在等待时释放锁,让其他线程有机会修改共享数据,并在条件满足时被精准唤醒。
它最经典的应用场景就是生产者-消费者模型(例如:缓冲区满了生产者要等,缓冲区空了消费者要等)。
💡 Condition 的核心方法
Condition 对象内部自带一把锁(默认是 RLock),它的所有核心操作都必须在这把锁的保护下进行(通常使用 with 语句):
| 方法 | 作用 | 通俗解释 |
|---|---|---|
acquire() / release() |
获取/释放内部的锁 | 进出门要记得开关门(通常用 with 代替) |
wait(timeout=None) |
释放锁并阻塞等待 | “我先让出资源,等条件满足了再叫醒我” |
notify(n=1) |
唤醒 1个 等待的线程 | “条件变了,叫醒其中 1 个人来看看” |
notify_all() |
唤醒 所有 等待的线程 | “条件变了,大家都起来看看” |
🛠️ 基础用法:生产者-消费者模型
下面通过一个经典的案例,展示 Condition 是如何协调两个线程对同一个共享资源(列表缓冲区)进行操作的:
import threading
import time
import random
# 共享资源(缓冲区)
buffer = []
MAX_SIZE = 5
# 创建 Condition 对象
condition = threading.Condition()
def producer():
"""生产者:不断生产数据放入缓冲区"""
while True:
with condition: # 自动获取锁
# 如果缓冲区满了,就等待消费者消费
while len(buffer) >= MAX_SIZE:
print("【生产者】缓冲区已满,等待消费者消费...")
condition.wait() # 释放锁,并阻塞等待
# 生产数据
item = random.randint(1, 100)
buffer.append(item)
print(f"【生产者】生产了数据: {item}, 当前库存: {len(buffer)}")
# 生产完毕,通知等待的消费者
condition.notify()
time.sleep(random.uniform(0.1, 0.5)) # 模拟生产耗时
def consumer():
"""消费者:不断从缓冲区取出数据"""
while True:
with condition: # 自动获取锁
# 如果缓冲区空了,就等待生产者生产
while len(buffer) == 0:
print("【消费者】缓冲区已空,等待生产者生产...")
condition.wait() # 释放锁,并阻塞等待
# 消费数据
item = buffer.pop(0)
print(f"【消费者】消费了数据: {item}, 当前库存: {len(buffer)}")
# 消费完毕,通知等待的生产者
condition.notify()
time.sleep(random.uniform(0.1, 0.5)) # 模拟消费耗时
# 启动线程
t1 = threading.Thread(target=producer)
t2 = threading.Thread(target=consumer)
t1.start()
t2.start()
⚠️ 避坑指南与最佳实践
在使用 Condition 时,有几个极其重要的细节需要注意,否则很容易出现死锁或逻辑错误:
- 必须使用
while循环检查条件:
调用wait()时,一定要写成while not condition_met: wait(),而不能用if。因为线程可能会被“虚假唤醒”(即没有被 notify 却自己醒了),用while可以在醒来后再次确认条件是否真的满足。 - 必须在持有锁的情况下调用:
wait()、notify()和notify_all()都必须在with condition:代码块(或者手动acquire()之后)调用,否则会直接抛出RuntimeError异常。 notify()不会释放锁:
调用notify()只是把等待的线程叫醒,但不会释放当前的锁。被叫醒的线程必须等到你退出with代码块(锁被释放)后,才能重新获取锁并继续执行。wait()会自动释放锁:
这是 Condition 最精妙的地方。当线程执行到wait()时,它会自动释放锁,这样其他线程才有机会获取锁并修改共享数据。
简单来说,需要多个线程之间进行复杂的“你做完我再做”、“没资源我就等,有资源你就叫醒我”的协作时,Condition 就是最合适的工具。

浙公网安备 33010602011771号