信号量:semaphore
信号量是用来控制线程并发数的。(理解:虽然GIL任意时刻都只有一个线程被执行,但是所有线程都有资格去抢,semaphore就是用来控制抢的GIL的数量,只有获取了semaphore的线程才有资格去抢GIL,起到了限制线程并发数的作用)
import threading import time class MyThread(threading.Thread): def run(self): if semap.acquire(): print(semap) print(self.name) time.sleep(5) semap.release() semap = threading.Semaphore(5) # 括号内如果没有指定数据,默认为1 thrs = [] for i in range(100): thrs.append(MyThread()) for i in thrs: i.start()
semaphore也是一把锁,这把锁内部有一个计数器,被acquire()的时候-1,release()的时候+1,当计数器为0的时候,其它线程将被阻塞。
semaphore和RLock都可以被重复获取,也都有计数器,区别是:semaphore是被不同线程获取,而RLock只能被同一线程重复获取。
条件变量:不仅能实现锁的功能,而且能够实现类似线程间的通信功能
用于一个标志符来实现线程间通信
threading.Condition([Lock/Rlock]):锁是可选选项,不传入锁,对象自动创建一个Rlock(0
wait():条件不满足时调用,线程会释放锁并进入等待阻塞
notify():条件创造后调用,通知等待池激活一个线程
notifyAll():条件创造后调用,通知等待池激活所有线程
import threading from random import randint import time class Producer(threading.Thread): def run(self): global L while 1: lock_con.acquire() r = randint(0, 100) print(self.name + "已生产" + str(r)) L.append(r) lock_con.notify() lock_con.release() time.sleep(1) class Consumer(threading.Thread): def run(self): global L while 1: lock_con.acquire() if len(L) == 0: lock_con.wait() print("消费者吃了"+str(L[0])) del L[0] lock_con.release() if __name__ == '__main__': L = [] lock_con = threading.Condition() threads = [] for i in range(5): threads.append(Producer()) threads.append(Consumer()) for i in threads: i.start()
要想实现两个线程之间的通信,两个线程用的必须是同一把锁,不然无法起到作用。
条件同步(Event)
条件同步和条件变量同步差不多,只是少了锁的功能,因为条件同步设计于不访问共享资源的环境。
event = threading.Event():条件环境变量,初始值为False
event.isSet():返回event的状态值
event.set():设备event的状态值为True,所有阻塞池的线程激活进入就绪状态,等待操作系统调试。
event.clear():设置event的状态值为False
event.wait():如果event的状态值为False时,阻塞线程
实例1:
import threading import time class Boss(threading.Thread): def run(self): print("今晚要加班!!!!") event.set() time.sleep(5) print("已经10点了,可以下班了!") event.set() class Work(threading.Thread): def run(self): event.wait() print("命苦啊!!!!") event.clear() event.wait() print("oh,yeah!") if __name__ == '__main__': event = threading.Event() threads = [] for i in range(3): threads.append(Work()) threads.append(Boss()) for i in threads: i.start() for i in threads: i.join()
实例2:红绿灯
import threading import time import random def ligth(): if not event.isSet(): event.set() count = 0 while 1: if count < 10: print("this light is green!") elif count < 13: print("the light is yellow!") elif count < 20: if event.isSet(): event.clear() print("the light is red!") else: count = 0 event.set() time.sleep(1) count += 1 def car(n): while 1: time.sleep(random.randrange(10)) if event.isSet(): print("car %s is running" % n) else: print("car %s is waiting for red light..." % n) event = threading.Event() Light = threading.Thread(target=ligth) Light.start() for i in range(3): t = threading.Thread(target=car,args=(i,)) t.start()