在 Python 中,Condition 对象用于线程同步,其 wait() 方法用于释放锁并阻塞线程,直到被其他线程唤醒。使用不当可能导致死锁、虚假唤醒或逻辑错误。以下是常见问题及修复方案:
常见问题与修复方案
1. 未检查条件(虚假唤醒)
-
问题:
wait()可能被虚假唤醒(即使未收到notify()),若用if检查条件,唤醒后可能条件仍未满足。python
with cond: if not resource_ready: # ❌ 错误:应用 while 而非 if cond.wait() -
修复:始终用
while循环检查条件:python
with cond: while not resource_ready: # ✅ 正确:循环检查条件 cond.wait()
2. 未在持有锁时调用 wait()
-
问题:调用
wait()前未获取关联锁,抛出RuntimeError。python
cond = threading.Condition() cond.wait() # ❌ 错误:未先获取锁
-
修复:确保在
with块或acquire()/release()中调用:python
with cond: # ✅ 正确:自动获取/释放锁 while not ready: cond.wait()
3. 未正确配对 notify() 和 wait()
-
问题:
notify()未在修改条件的代码块中调用,导致信号丢失。python
def producer(): resource_ready = True # ❌ 错误:未在锁内修改条件 cond.notify() # 可能错过唤醒 -
修复:修改条件和调用
notify()必须在同一锁内:python
def producer(): with cond: resource_ready = True # ✅ 在锁内修改条件 cond.notify() # 安全唤醒
4. 未使用超时导致永久阻塞
-
问题:若生产者线程失败,消费者可能永久阻塞。
-
修复:为
wait()添加timeout参数并处理超时:python
with cond: while not resource_ready: if not cond.wait(timeout=5.0): # 等待5秒 print("Timeout, exiting") break
5. 错误使用 notify() 而非 notify_all()
-
问题:
notify()只唤醒一个线程,若多个线程等待相同条件,可能遗漏唤醒。 -
修复:需要唤醒所有线程时使用
notify_all():python
with cond: resource_ready = True cond.notify_all() # ✅ 唤醒所有等待线程
完整正确示例
python
import threading
# 共享资源与条件变量
resource_ready = False
cond = threading.Condition()
def consumer():
with cond:
while not resource_ready: # 循环检查条件
cond.wait() # 释放锁并等待
print("Resource is ready!")
def producer():
with cond:
global resource_ready
resource_ready = True # 修改条件
cond.notify_all() # 唤醒所有等待线程
# 启动线程
threading.Thread(target=consumer).start()
threading.Thread(target=producer).start()
关键实践总结
-
检查条件:始终用
while循环检查条件(防虚假唤醒)。 -
锁的作用域:
wait()、notify()及条件修改必须在同一锁内。 -
唤醒选择:
-
notify():唤醒 1 个线程(效率高)。 -
notify_all():唤醒 所有线程(避免遗漏)。
-
-
超时机制:用
wait(timeout=seconds)防止永久阻塞。 -
资源状态:条件变量应关联明确的共享状态(如
resource_ready)。
遵循这些模式可避免 Condition 的常见陷阱,确保线程安全。
1467

被折叠的 条评论
为什么被折叠?



