信号量(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