什么是事件?
事件在内部管理了一个标志Flag
,如果Flag
值为 False
,那么线程在执行event.wait
方法时就会阻塞等值直到Flag值为True
,该线程便会顺利执行,而Flag
的值是通过event.set()
和event.clear()
设定的:
-
set(): 将标志设为
True
,并通知所有处于等待阻塞状态的线程恢复运行状态。 -
clear(): 将标志设为
False
。 -
wait(timeout): 如果标志为
True
将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()
。 -
isSet(): 获取内置标志状态,返回
True
或False
。
而Event其实就是一个简化版的 Condition。Event没有锁,无法使线程进入同步阻塞状态,所以当个多个线程处于wait
状态时,一旦标志位Flag
变为真时,这些线程便会 “同时” (GIL锁的原因,假装在同时执行)执行。
简单的生产者-消费者模型
通过事件,我们也可以实现一个简单的生产者-消费者模型:
import threading
import random
import time
# 假定商品序号
goods = 0
# 定义一个事件
event = threading.Event()
def consumer():
time.sleep(0.5)
print(threading.currentThread().getName() + ' consumer is wait for goods.')
# 等待事件,进入阻塞状态
event.wait()
print(threading.currentThread().getName() + ' consumer gets the goods: {}\n'.format(goods))
def producer():
global goods
time.sleep(1)
goods = random.randint(1, 11)
print('producer makes the goods: {}\n'.format(goods))
time.sleep(1)
# Flag --> True
event.set()
if __name__ == "__main__":
thread_consumer1 = threading.Thread(target=consumer)
thread_consumer2 = threading.Thread(target=consumer)
thread_producer = threading.Thread(target=producer)
thread_consumer1.start()
thread_consumer2.start()
thread_producer.start()
thread_consumer1.join()
thread_consumer2.join()
thread_producer.join()
print('consumer-producer example end.')
运行截图如下:
我们可以看到,两个消费者都在阻塞等待商品的生产,而一旦生产者通知商品生产成功(event.set()
--> Flag=True
),消费者们便都会得到该商品,这样看来,event 看似就是condition的简化版本,只是没了锁,线程们不能同步阻塞对共享资源的访问。