zoukankan      html  css  js  c++  java
  • 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(): #每次最大5个线程运行,具体哪些线程运行,系统自动调配。
    print(self.name)
    time.sleep(3)
    semaphore.release()

    if __name__=="__main__":
    semaphore=threading.Semaphore(5) #每次最大5个线程运行
    thrs=[]
    for i in range(100): #创建了100个线程。
    thrs.append(myThread())
    for t in thrs:
    t.start() #启动了100个线程。

    实例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()

     信号量的主要作用:

      主要用在数据库应用中,比如连接数据库的连接,限制同时连接的数量,如数据库连接池。

  • 相关阅读:
    Eclipse RCP应用程序无法关闭,需在进程栏关闭
    JAVA代码BUG检测工具
    Eclipse客户端程序中多线程的使用(转载)
    geotools获取shapefile 属性名乱码问题
    近距离P2P通讯技术平台 Alljoyn
    Eclipse a tale of two VMs (and many classloaders) (转载)
    深入 Eclipse 多线程机制(转载)
    Top 10 mistakes in Eclipse Plugin Development
    EclipseRCP软件的P2升级资料收集
    java事件处理机制 自定义事件(转载)
  • 原文地址:https://www.cnblogs.com/chenhaiming/p/9915702.html
Copyright © 2011-2022 走看看