Event不同于Lock、Condition等互斥工具,Event主要用于同步,所谓同步就是让多个线程按照事先设计好的顺序先后运行,相互配合完成一个工作。
基本原理
Lock等工具主要用于共享资源的访问,而Event适用于没有共享资源的情形,主要作用是在线程间传递消息,A线程对B线程说:我做完了,该你了。因为不涉及锁的竞争,只是单纯等消息,因此Event比Lock效率高。不可否认,Lock也能在线程间传递消息,但效率很差,我们来对比一下:
A线程给B线程传递消息:
使用Lock:还要有一个缓冲区buffer,A先锁定buffer,把消息写入buffer,A释放锁,B锁定buffer,读取buffer中的消息,B释放锁。
使用Event:A和B共同拥有同一个Event,A调用set()方法,消息就给B传递过去了。
可见Event是很轻量级的,当然,Event传递的消息非常有限,只能传过去一个True值,不能传其他的。
主要方法
代码语言:python代码运行次数:0复制set() # 发送消息,本质是把内置的flag设置为True
wait() # 等待消息,只要内置flag是False就阻塞线程
clear() #重置消息,也就是将内部flag设为False。宏观上看,消息是一次性的,想要重复使用消息,必须在每次使用后进行清除
小例子
我们来看一个多线程配合的例子,且没有共享数据。
在原神中,永冻队是一个很强力的队伍,神里、猫猫、心海、万叶各司其职,相互配合,打出爆炸性伤害。但这4个人的技能不能随意释放,必须有先后顺序。我们就编写4个线程,每个线程代表一个人,然后用Event严格控制他们的执行顺序。
具体的顺序如下:
1.猫猫 长E挂冰
2.万叶 释放QE扩散冰元素,增加冰伤
3.心海 放E,用水母给怪挂水
4.神里 释放大招,打出超高伤害
为了便于观察结果,每个线程运行10轮就结束。
那么这个例子里面,需要几个Event呢?答案是4个,猫猫通知万叶是第一个,万叶通知心海是第二个,心海通知神里是第三个,神里通知猫猫是第四个。
代码如下:
代码语言:python代码运行次数:0复制import threading
# 使用Event进行线程同步
# 模拟原神永冻队释放技能
def maomao(event1:threading.Event, event2:threading.Event):
'''猫猫第一个释放技能'''
for i in range(1, 11):
event1.wait()
event1.clear()
print('1.猫猫 长E挂冰')
event2.set()
def wanye(event2:threading.Event, event3:threading.Event):
'''万叶第二个释放技能'''
for i in range(1, 11):
event2.wait()
event2.clear()
print('2.万叶 释放QE扩散冰元素,增加冰伤')
event3.set()
def xinhai(event3:threading.Event, event4:threading.Event):
'''心海第三个释放技能'''
for i in range(1, 11):
event3.wait()
event3.clear()
print('3.心海 放E,用水母给怪挂水')
event4.set()
def shenli(event4:threading.Event, event1:threading.Event):
'''神里第四个释放技能'''
for i in range(1, 11):
event4.wait()
event4.clear()
print('4.神里 释放大招,打出超高伤害n')
event1.set()
e1 = threading.Event()
e2 = threading.Event()
e3 = threading.Event()
e4 = threading.Event()
t1 = threading.Thread(target=maomao, args=(e1, e2))
t2 = threading.Thread(target=wanye, args=(e2, e3))
t3 = threading.Thread(target=xinhai, args=(e3, e4))
t4 = threading.Thread(target=shenli, args=(e4, e1))
e1.set() #通知 猫猫 可以放技能了
t4.start()
t3.start()
t2.start()
t1.start()
t1.join()
t2.join()
t3.join()
t4.join()
print('n经过10轮技能释放,怪物被消灭,程序结束')