一、信号量:某一段代码同一时间只能被n个进程执行 例子: #信号量:控制并发数 import threading import time def run(n): semaphore.acquire() #启动事件量 print(n) time.sleep(1) semaphore.release()#释放事件量 if __name__ == '__main__': semaphore = threading.Semaphore(5)#一次运行五个线程,其中一个线程结束锁释放 for i in range(50): t = threading.Thread(target=run,args=(i,)) t.start()
二、Condition(条件变量)通常与一个锁关联。需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例。
可以认为,除了Lock带有的锁定池外,Condition还包含一个等待池,池中的线程处于状态图中的等待阻塞状态,直到另一个线程调用notify()/notifyAll()通知;得到通知后线程进入锁定池等待锁定。
Condition():
- acquire(): 线程锁
- release(): 释放锁
- wait(timeout): 线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。
- notify(n=1): 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。notify()不会主动释放Lock。
- notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程
'''条件变量''' import threading import time def run(x): con.acquire() print(f'线程{x}') con.notify() #告诉下边一个线程wait结束 print(f'线程{x}挂起') con.wait() time.sleep print(f'线程{x}再次启动') con.notify() con.release() if __name__ == '__main__': con = threading.Lock() #实例化条件变量 # for i in range(10): t = threading.Thread(target=run,args=(1,)) t.start() 例子:实现场景:当a同学王火锅里面添加鱼丸加满后(最多5个,加满后通知b去吃掉),通知b同学去吃掉鱼丸(吃到0的时候通知a同学继续添加)
# coding=utf-8 import threading import time con = threading.Condition() num = 0 # 生产者 class Producer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): # 锁定线程 global num con.acquire() while True: print "开始添加!!!" num += 1 print "火锅里面鱼丸个数:%s" % str(num) time.sleep(1) if num >= 5: print "火锅里面里面鱼丸数量已经到达5个,无法添加了!" # 唤醒等待的线程 con.notify() # 唤醒小伙伴开吃啦 # 等待通知 con.wait() # 释放锁 con.release() # 消费者 class Consumers(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): con.acquire() global num while True: print "开始吃啦!!!" num -= 1 print "火锅里面剩余鱼丸数量:%s" %str(num) time.sleep(2) if num <= 0: print "锅底没货了,赶紧加鱼丸吧!" con.notify() # 唤醒其它线程 # 等待通知 con.wait() con.release() p = Producer() c = Consumers() p.start() c.start()
三、事件
(1)一个信号可以使所有的进程进入阻塞状态
(2)也可以控制所有的进程解除阻塞
(3)一个事件被创建之后,默认是阻塞状态
例子:
import threading import time def car(): while True: if event.is_set(): #如果事件在执行 print('小车行驶') else: print('小车停止') event.wait() #等待事件 def set_event(): while True: event.set() #启动事件 time.sleep(1) event.clear() #清除事件 time.sleep(1) if __name__ == '__main__': event = threading.Event() #创建事件 car1 = threading.Thread(target=car) car1.start() set_e = threading.Thread(target=set_event) set_e.start()
视频讲解:https://space.bilibili.com/196858266/channel/collectiondetail?sid=57996