信号量(Semaphore)
信号量是用来控制线程并发数的,boundedSemaphore或Semaphore管理一个内置的计数器,每当调用acquire()时减一,调用release()时加一
计数量不能小于0,当计数器为0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()
BoundedSemaphore与Semaphore的区别在于前者将在调用release()时检查计数器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。
import threading, time
class myThread(threading.Thread):
def run(self):
if semaphore.acquire():
print(self.name)
time.sleep(5)
semaphore.release()
if __name__ == '__main__':
semaphore = threading.BoundedSemaphore(4)
threads = []
for i in range(23):
threads.append(myThread())
for t in threads:
t.start()
运行结果:
semaphore = threading.BoundedSemaphore(4)意思就是创建一个锁,每次只能4个线程并发。
如图所示
条件变量同步(Condition)
- 有一类线程需要满足条件之后才能够执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock() 方法外,还提供了wait()、notify()、notifyAll()方法。
wait():条件不满足时调用,线程会释放锁并进入等待阻塞。
notify():条件创建后调用,通知等待池激活另一个线程。
notifyAll():条件创造后调用,通知等待池激活所有线程。
import threading, time
from random import randint
class Producer(threading.Thread):
def run(self):
global L
while True:
val = randint(0, 100)
print('生产者', self.name,":Append" + str(val),L)
if lock_con.acquire():
L.append(val)
lock_con.notify()
lock_con.release()
time.sleep(3)
class Consumer(threading.Thread):
def run(self):
global L
while True:
lock_con.acquire()
if len(L)==0:
lock_con.wait() # 并非从阻塞的地方开始运行
# print("ok!!")
print('消费者',self.name,":Delete" + str(L[0]),L)
del L[0]
lock_con.release()
time.sleep(1)
if __name__ == '__main__':
L = []
lock_con = threading.Condition()
threads = []
for i in range(5):
threads.append(Producer())
threads.append(Consumer())
for t in threads:
t.start()
运行结果:
程序步骤大致如图所示:
同步条件(Event)
条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问公共资源的条件环境。event=threading.Event():条件环境对象,初始值为False:
- event.isSet():返回event的状态值
- event.wait():如果event的状态值为False将阻塞线程
- event.set():设置event的状态值为True,所有阻塞池的线程激活进入就绪状态,等待操作系统的调度。
- event.clear():恢复event的状态值为False。
import threading, time
class Boss(threading.Thread):
def run(self):
print("Boss: 今晚大家都加班到22:00")
event.isSet() or event.set()
time.sleep(5)
print("Boss : 22:00了,大家可以下班了")
event.isSet() or event.set()
class Worker(threading.Thread):
def run(self):
event.wait()
print("Worker: 哎呀呀")
time.sleep(0.25)
event.clear()
event.wait()
print("Worker: nice day")
if __name__ == '__main__':
event = threading.Event()
threads = []
for i in range(5):
threads.append(Worker())
threads.append(Boss())
for t in threads:
t.start()
运行结果
Boss: 今晚大家都加班到22:00
Worker: 哎呀呀
Worker: 哎呀呀
Worker: 哎呀呀
Worker: 哎呀呀
Worker: 哎呀呀
Boss : 22:00了,大家可以下班了
Worker: nice day
Worker: nice day
Worker: nice day
Worker: nice day
Worker: nice day