PYTHON——多线程:信号量(Semaphore)

  信号量也是一把锁,用来控制线程并发数的

  BoundedSemaphore或Semaphore管理一个内置的计数 器,每当调用acquire()时-1,调用release()时+1。

      计数器不能小于0,当计数器为 0时,acquire()将阻塞线程至同步锁定状态,直到其他线程调用release()。(类似于停车位的概念)

      BoundedSemaphore与Semaphore的唯一区别在于前者将在调用release()时检查计数 器的值是否超过了计数器的初始值,如果超过了将抛出一个异常。

实例1:

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.Semaphore(5)
    thrs=[]
    for i in range(100):
        thrs.append(myThread())
    for t in thrs:
        t.start()

实例2:

  本例通过信号量(Semaphore)和线程锁模拟了一个糖果机补充糖果和用户取走糖果的过程,糖果机有5个槽,如果发现某个槽没有糖果了,则需要补充新的糖果。当5个槽都装满时,无法补充新的糖果。如果5个槽都是空的,则用户无法购买糖果。为了便于说明问题,本例假设顾客一次会购买整个槽的糖果,每次补充整个槽的糖果。

from atexit import register
from random import randrange
from threading import BoundedSemaphore,Lock,Thread
from time import sleep,ctime

#创建线程锁
lock= Lock()
#定义糖果的槽数,也是信号量计数器的最大值
MAX=5
#创建信号量对象,并指定计数器的最大值
candytray = BoundedSemaphore(MAX)
#给糖果机的槽补充新的糖果(每次只补充一个槽)
def refill():
    #获取线程锁,将补充的糖果的操作变成原子操作
    lock.acquire()
    print('重新添加糖果......',end=' ')
    try:
        #为糖果机的槽补充糖果(计数器+1)
        candytray.release()
    except ValueError:
        print('糖果机都满了,无法添加')
    else:
        print('成功添加糖果')
    lock.release()

#顾客购买糖果
def buy():
    lock.acquire()
    print('购买糖果......',end=' ')
    #顾客购买糖果(计数器-1),如果购买失败(5个槽都没有糖果了),返回False
    if candytray.acquire(False):
        print('成功购买糖果')
    else:
        print('糖果机为空,无法购买糖果')
    lock.release()

def producer(loops):
    for i in range(loops):
        refill()
        sleep(randrange(3))

#产生多个购买糖果的动作
def consumer(loops):
    for i in range(loops):
        buy()
        sleep((randrange(3)))

def main():
    print('开始:',ctime())
    nloops = randrange(2,6)
    print('糖果机共有%d个槽!' % MAX)
    #开始一个线程,用于执行consumer函数
    Thread(target=consumer,args=(randrange(nloops,nloops+MAX+2),)).start()
    #开始一个线程,用于执行producer函数。
    Thread(target=producer,args=(nloops,)).start()

@register
def exit():
    print('程序执行完毕:',ctime())

if __name__ == '__main__':
    main()

猜你喜欢

转载自www.cnblogs.com/chenhaiming/p/9915702.html