Python学习之路并发编程--信号量事件队列及生产消费模型

Posted ys-0717

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()      # 感知一个进程的结束

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

以上是关于Python学习之路并发编程--信号量事件队列及生产消费模型的主要内容,如果未能解决你的问题,请参考以下文章

python 闯关之路四(下)(并发编程与数据库编程) 并发编程重点

python 闯关之路四(上)(并发编程与数据库理论)

python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式

Python之进程同步控制(锁信号量事件 )进程间通信——队列和管道

并发编程-进程中的锁信号量 事件和队列

python之路——进程