信号量
信号量又称:Semaphore类 迭代锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据,比如一个地方有3个座位, 那最多只允许3个人坐,后面的人只能等有人起来了才能再坐人
def run(n,semaphore):
semaphore.acquire() #加锁
time.sleep(3)
print('run the thread:%s\n' % n)
semaphore.release() #释放
if __name__== '__main__':
num=0
semaphore = threading.Semaphore(5) #最多允许5个线程同时运行
for i in range(10):
t = threading.Thread(target=run,args=('t-%s' % i,semaphore))
t.start()
while threading.active_count() !=1:
pass
else:
print('all threads done')
条件变量
Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。
def A(cond):
with cond:
print(1)
cond.notify()
cond.wait()
print(3)
cond.notify()
cond.wait()
def B(cond):
with cond:
cond.wait()
print(2)
cond.notify()
cond.wait()
print(4)
if __name__ == "__main__":
cond = threading.Condition()
t1 = threading.Thread(target=A, args=(cond,))
t2 = threading.Thread(target=B, args=(cond,))
t2.start()
t1.start()
t1.join()
t2.join()
事件
如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在 初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行。
from threading import Thread,Event
import time
event=Event()
def light():
print('红灯正亮着')
time.sleep(3)
event.set() #绿灯亮
def car(name):
print('车%s正在等绿灯' %name)
event.wait() #等灯绿 此时event为False,直到event.set()将其值设置为True,才会继续运行.
print('车%s通行' %name)
if __name__ == '__main__':
# 红绿灯
t1=Thread(target=light)
t1.start()
# 车
for i in range(10):
t=Thread(target=car,args=(i,))
t.start()
实例
第一个线程中获取当前时间,判断当前时间3秒之后,触发“事件” 对象。在另 一个线程中,作为数学考试结束的判断变量,否则一直处于考试中,并打印。
import threading#导入线程类
import time#导入python中的time类
class Eventthread(threading.Thread):#定义事件监听类继承于Thread类
def __init__(self):#定义构造方法
super(Eventthread, self).__init__()#重写Thread类的构造方法初始化self属性
def run(self):#重写Thread类的run方法,执行实际逻辑结构
for i in range(3): #for语句循环3秒
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) #以%Y-%m-%d %H:%M:%S的格式输出显示当前的时间
time.sleep(1) #使线程挂起1秒,减少输出次数
event.set()# 设置事件响应
class Mythread(threading.Thread):#自定义线程类继承于Thread类
def __init__(self):#定义构造方法
super(Mythread, self).__init__()#重写Thread类的构造方法初始化self属性
def run(self):#重写Thread类的run方法,执行实际逻辑结构
while(True): #循环判断事件是否响应
print("考试中") #若事件未响应则输出“考试中”的信息
time.sleep(1) #使线程挂起1秒,减少输出次数
if event.is_set(): #若事件响应
print("考试结束!") #则输出“考试结束”的信息
break #并跳出循环
if __name__=='__main__': #创建主线程
event = threading.Event() #初始化event对象
mt = Mythread() #初始化一个线程对象
et = Eventthread() #初始化一个线程对象
mt.start() #启动线程
et.start() #启动线程