zoukankan      html  css  js  c++  java
  • Python学习之路并发编程--信号量、事件、队列及生产消费模型

    1. 信号量  

      对于多进程来说,多个进程同时修改数据,就可能出现安全隐患,所以引入了锁,这一机制,但锁只能有一把来控制一个的开关,当你需要几把锁的时候,就可能用到信号量的概念。他是用了锁的原理,内置了一个计数器,在同一时内,只能有指定数量的进程来执行某一段被控制的代码。

    import time,random
    from multiprocessing import Process,Semaphore
    
    def singing(i,sem):
        '''
        :param i: 随机生成20个数的值
        :param sem:生成的信号量
        :return:None
        '''
        sem.acquire()#获得锁
        print('%s is coming '%i)
        time.sleep(random.randint(10,20))#随机在10秒至20秒中停顿
        print('%s is going out'%i)
        sem.release()#释放锁
    
    if __name__ == '__main__':
        sem = Semaphore(4)#生成4个锁
        for i in range(20):
            p = Process(target=singing,args=(i,sem))
            p.start()

    2. 事件

      事件是通过一个信号来控制多个进程的同时执行或阻塞,当一个事件被创建的时候默认是阻塞状态,但不影响进程的执行,当遇到 even.wait() 方法时,才会阻塞。

    # set 和 clear
    #      分别用来修改一个事件的状态 True或者False
    # is_set 用来查看一个事件的状态
    # wait 是依据事件的状态来决定自己是否在wait处阻塞
    #      False阻塞 True不阻塞

      下面是一个红绿灯的问题。

    import time
    import random
    from multiprocessing import Event,Process
    
    def cars(e,i):
        '''
        一个判断车是否通过的函数
        :param e: 传入一个事件
        :param i: 生成的车几
        :return: None
        '''
        if not e.is_set():
            print('33[0;31;40mcar %s 在等待~33[0m'%i)
            e.wait()
        print('33[32;40mcar %s 通过~33[0m'%i)
    
    def light(e):
        '''
        控制红绿灯的切换
        :param e: 传入事件
        :return: None
        '''
        while True:
            if e.is_set():
                e.clear()
                print('33[31m红灯亮了33[0m')
                time.sleep(3)
            else:
                e.set()
                print('33[32m绿灯亮了33[0m')
                time.sleep(5)
    
    if __name__ == '__main__':
        e = Event()
        traffic = Process(target=light,args=(e,))
        traffic.start()
        time.sleep(1)
        for i in range(random.randint(5,10)):
            car = Process(target=cars,args=(e,i))
            car.start()
            time.sleep(random.randint(1,3))

    3. 队列

      队列 Queue 中只有少数几个方法,

        # put  当队列满的时候阻塞等待队列有空位置
        # get  当队列空的时候阻塞等待队列有数据
        # full empty 不完全准确

      full 和 empty 不准一原因在于,如果队列回答主程序时,同时进程又对队列进行了操作,这个就会造成数据的错误。

    4. 用 JoinableQueue 来处理生产者和消费者模型

    import time
    import random
    from multiprocessing import Process,JoinableQueue
    
    
    def producer(name,food,q):
        for i in range(4):
            time.sleep(random.randint(1,3))
            f = '%s生产了%s%s'%(name,food,i)
            print(f)
            q.put(f)
        q.join()    # 阻塞  直到一个队列中的所有数据 全部被处理完毕
    
    def consumer(q,name):
        while True:
            food = q.get()
            print('33[31m%s消费了%s33[0m' % (name,food))
            time.sleep(random.randint(1,3))
            q.task_done()     # count - 1
    
    if __name__  == '__main__':
        q = JoinableQueue(20)
        p1 = Process(target=producer,args=('eli','dumpling',q))
        p2 = Process(target=producer, args=('tom','noodle', q))
        c1 = Process(target=consumer, args=(q,'mike'))
        c2 = Process(target=consumer, args=(q,'johan'))
        p1.start()
        p2.start()
    
        c1.daemon = True   # 设置为守护进程 主进程中的代码执行完毕之后,子进程自动结束
        c2.daemon = True
    
        c1.start()
        c2.start()
        p1.join()
        p2.join()      # 感知一个进程的结束

      觉得最好的点就是用到了守护进程(当主进程的程序执行完成时,子进程也随之结束)。

  • 相关阅读:
    PythonStudy——数据类型总结 Data type summary
    PythonStudy——可变与不可变 Variable and immutable
    PythonStudy——列表操作 List operatio
    PythonStudy——列表的常用操作 List of common operations
    PythonStudy——列表类型 List type
    PythonStudy——字符串扩展方法 String extension method
    PythonStudy——字符串重要方法 String important method
    AWT,Swing,RCP 开发
    JQuery插件机制
    最新知识网站
  • 原文地址:https://www.cnblogs.com/YS-0717/p/9742137.html
Copyright © 2011-2022 走看看