本文目录导读:

在Python中实现线程的等待与唤醒,主要使用threading模块中的Event、Condition或Semaphore等同步原语,以下是几种常见实现方式:
使用 Event(最常用)
Event是最简单的线程间通信机制,支持 wait() 和 set()/clear()。
import threading
import time
# 创建事件对象
event = threading.Event()
def waiter():
print("等待者:等待事件...")
event.wait() # 阻塞等待事件被设置
print("等待者:接收到事件,继续执行")
def setter():
print("设置者:准备设置事件")
time.sleep(3) # 模拟一些工作
event.set() # 设置事件,唤醒等待线程
print("设置者:事件已设置")
# 创建线程
t1 = threading.Thread(target=waiter)
t2 = threading.Thread(target=setter)
t1.start()
t2.start()
t1.join()
t2.join()
使用 Condition(支持精确唤醒)
Condition提供更细粒度的控制,可以结合 notify()/notify_all() 精确唤醒。
import threading
import time
condition = threading.Condition()
shared_data = []
DATA_READY = False
def consumer():
with condition:
print("消费者:等待数据...")
while not DATA_READY: # 必须用while循环检查条件
condition.wait() # 释放锁并等待
print("消费者:获取到数据:", shared_data)
def producer():
global DATA_READY
time.sleep(2) # 模拟生产数据
with condition:
shared_data.append("重要数据")
DATA_READY = True
print("生产者:通知消费者")
condition.notify() # 唤醒一个等待线程
t1 = threading.Thread(target=consumer)
t2 = threading.Thread(target=producer)
t1.start()
t2.start()
t1.join()
t2.join()
使用 Semaphore(信号量)
信号量控制同时访问资源的线程数量,也可用于线程间同步。
import threading
import time
semaphore = threading.Semaphore(0) # 初始值为0
def waiter():
print("等待者:等待信号量...")
semaphore.acquire() # 阻塞等待信号量>0
print("等待者:获得信号量,继续执行")
def setter():
print("设置者:释放信号量")
time.sleep(2)
semaphore.release() # 释放信号量,增加计数
t1 = threading.Thread(target=waiter)
t2 = threading.Thread(target=setter)
t1.start()
t2.start()
使用 queue.Queue(生产者-消费者模式)
对于简单的数据传递场景,使用队列更安全、更方便。
import threading
import time
import queue
q = queue.Queue()
def consumer():
print("消费者:等待数据...")
data = q.get() # 阻塞等待队列非空
print("消费者:获取到:", data)
def producer():
time.sleep(2)
data = "重要数据"
q.put(data) # 放入队列
print("生产者:已放入数据")
t1 = threading.Thread(target=consumer)
t2 = threading.Thread(target=producer)
t1.start()
t2.start()
选择建议
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 简单一次性等待 | Event |
最简洁,适合一次性的通知 |
| 条件精确控制 | Condition |
支持精确唤醒特定线程 |
| 资源访问控制 | Semaphore |
控制并发访问数量 |
| 数据传递 | Queue |
线程安全的队列,自动处理同步 |
| 周期性任务 | Timer |
定时执行特定功能 |
注意事项
- 虚假唤醒:使用
Condition时,必须用while循环检查条件 - 死锁预防:确保锁的获取和释放成对出现,避免嵌套锁
- 超时处理:大多数等待方法支持
timeout参数 - 线程安全:共享数据的读写需要在锁的保护下进行
# 带超时的等待示例
event = threading.Event()
event.wait(timeout=5) # 最多等待5秒
if event.is_set():
print("事件已设置")
else:
print("等待超时")
根据具体需求选择合适的同步机制,可以让线程间的协作更加高效和安全。