线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。
在初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象,而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真;它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件,继续执行
Event()可以创建一个事件管理标志,该标志(event)默认为False,event对象主要有四种方法可以调用:
event.wait(timeout=None):调用该方法的线程会被阻塞,如果设置了timeout参数,超时后,线程会停止阻塞继续执行;
event.set():将event的标志设置为True,调用wait 方法的所有线程将被唤醒;
event.clear():将event的标志设置为Fa1se,调用wait方法的所有线程将被阻塞;
event.is_set():判断event的标志是否为True。
需求:
线程1,代表门,一开始是打开的,每3秒需要自动关闭一下,如果有人通过,需要重新刷卡打开
线程2,代表人,人通过门,如果门是打开的直接通过,如果没有打开需要刷卡,之后门就已经打开了,通知人继续进入
import threading
import time
import random
event = threading.Event() # 创建一个事件,事件默认为假
event.set() # 设置标志为真,门一开始是打开的
status = 0 # 代表门的状态,如果是0-3(不包括3)代表打开,如果等于3,代表关闭
def door():
global status
while True:
print('当前门的status为{}'.format(status))
if status >= 3:
print('当前门已经打开了3s,需要自动关闭')
event.clear()
if event.is_set():
print('当前门是开的,可以通行')
else:
print('门已经关了,请用户自己刷卡')
# status=0 #原来已经等于3了
event.wait() # 门的线程阻塞等待
continue
time.sleep(1)
status += 1 # status代表门开始的秒数
def person():
global status
n = 0 # 人的计数器,看看有多少人进入门里面
while True:
if event.is_set():
n += 1
print('门开的,{}号人进入门里面'.format(n))
else:
print('门关着,{}号人刷卡,进入门里面'.format(n))
event.set() # 标志改为true
status = 0
time.sleep(random.randint(1, 10))
if __name__ == '__main__':
d = threading.Thread(target=door)
p = threading.Thread(target=person)
d.start()
p.start()