zoukankan      html  css  js  c++  java
  • 第三十七天 管道、信号、信号量

    1.一段代码一段时间被一个人访问可以使用lock方法,如果一段代码同一时间被n个进程访问/或者说被n个进程执行用甚么指令?

      使用semaphore

      第一段代码:

    from multiprocessing import  Process,Semaphore
    import time
    def ktv(i):
        print('%s走了进来'%i)
        time.sleep(2)
        print('%s走了出来'%i)
    if __name__=='__main__':
        for i in range(20):
            s=Semaphore(4)
            p=Process(target=ktv,args=(i,))
            p.start()
    结果为
    3走了进来
    8走了进来
    0走了进来
    4走了进来
    6走了进来
    11走了进来
    10走了进来
    7走了进来
    5走了进来
    1走了进来
    12走了进来
    18走了进来
    15走了进来
    16走了进来
    2走了进来
    14走了进来
    9走了进来
    17走了进来
    13走了进来
    19走了进来
    3走了出来
    8走了出来
    0走了出来
    4走了出来
    6走了出来
    11走了出来
    10走了出来
    7走了出来
    5走了出来
    1走了出来
    12走了出来
    18走了出来
    15走了出来
    16走了出来
    2走了出来
    14走了出来
    9走了出来
    17走了出来
    13走了出来
    19走了出来
    View Code

    从结果我们可以发现所有人都可以进入此ktv但时此ktv只有4个房间,很明显不合理:

      第二段代码:

    from multiprocessing import  Process,Semaphore
    import time
    def ktv(i,s):
        s.acquire() #获取钥匙
        print('%s走了进来'%i)
        time.sleep(2)
        print('%s走了出来'%i)
        s.release()  #进行要是归还
    if __name__=='__main__':
        s=Semaphore(4)   #创建类并进行允许数量的控制,及一个计数信号量
        for i in range(20):
            p=Process(target=ktv,args=(i,s))
            p.start()
    
    结果为4走了进来
    3走了进来
    1走了进来
    8走了进来
    4走了出来
    0走了进来
    3走了出来
    6走了进来
    1走了出来
    2走了进来
    8走了出来
    7走了进来
    0走了出来
    11走了进来
    6走了出来
    10走了进来
    2走了出来
    14走了进来
    7走了出来
    5走了进来
    11走了出来
    13走了进来
    10走了出来
    17走了进来
    14走了出来
    9走了进来
    5走了出来
    16走了进来
    13走了出来
    12走了进来
    17走了出来
    18走了进来
    9走了出来
    15走了进来
    16走了出来
    19走了进来
    12走了出来
    18走了出来
    15走了出来
    19走了出来
    View Code

    2.信号:

    一个信号可以使所有的进程都进入堵塞状态,也可使所有控制的进程都接触堵塞状态,一个事件被创建之后,默认是堵塞状态

    from multiprocessing import Event
    a=Event()  #创建了一个事件的类
    print(a.is_set()) #查看现在事件的状态#默认状态时False
    a.wait()  
    print('1900')#如果事件状态为False则指令不执行
    结果为
    False
    View Code

      那么怎么才能让程序执行那:使用对象.set

    from multiprocessing import Event
    a=Event()  #创建了一个事件的类
    print(a.is_set()) #查看现在事件的状态#默认状态时False
    a.set()  #将事件状态转为True
    a.wait()
    print(a.is_set())
    print('1900')#如果事件状态为True则指令执行
    结果为
    False
    True
    1900
    View Code

      那么怎么才能把程序转为False

    from multiprocessing import Event
    a=Event()  #创建了一个事件的类
    print(a.is_set()) #查看现在事件的状态#默认状态时False
    a.set()  #将事件状态转为True
    a.wait()
    print(a.is_set())
    print('1900')#如果事件状态为True则指令执行
    a.clear()
    print(a.is_set())
    a.wait()#根据is_set的值来确定是否进行堵塞,没有这一步堵塞与否执行不起来
    print('12345')
    结果为
    False
    True
    1900
    False
    View Code

    总结:set和clear用来改变事件的运行状态,is_set()是用来判别事件现在的状态,wait根据is_set()的值来判断是否堵塞

    3.红绿灯程序 

    from multiprocessing  import Process
    import time
    def traffic_light():
        while True:
            print('33[31m红等亮了33[0m')
            time.sleep(3)
            print('33[32m绿灯亮了33[0m')
            time.sleep(3)
    if __name__=='__main__':
            p=Process(target=traffic_light)
            p.start()
    结果为
    C:pycharmpython.exe D:/python练习程序/第三十七天/practise.py
    红等亮了
    绿灯亮了
    红等亮了
    绿灯亮了
    红等亮了
    绿灯亮了
    红等亮了
    绿灯亮了
    红等亮了
    绿灯亮了
    红等亮了
    View Code

      如果再加一个车的程序,要求红灯车等待,绿灯车通行:

    from multiprocessing  import Process,Event
    import time
    def car(a,i):
        if a.is_set():
            a.wait()
            print('%s车进程等待'%i)
        else:
            a.wait()
            print('%s车通过'%i)
    def traffic_light(a):
        while True:
            if a.is_set():
                print('33[31m红等亮了33[0m')
                time.sleep(3)
                a.clear()
            else:
                print('33[32m绿灯亮了33[0m')
                time.sleep(3)
                a.set()
    if __name__=='__main__':
            a=Event()
            p=Process(target=traffic_light,args=(a,))
            p.start()
            for i in range(20):
                p1=Process(target=car,args=(a,i))
                p1.start()
                time.sleep(1)
    结果为
    绿灯亮了
    3车通过
    0车通过
    2车通过
    1车通过
    红等亮了
    4车进程等待
    5车进程等待
    6车进程等待
    绿灯亮了
    9车通过
    7车通过
    8车通过
    红等亮了
    10车进程等待
    11车进程等待
    绿灯亮了
    View Code

    4.队列的程序·:

      正常情况下:

    from multiprocessing import Queue
    q=Queue(4)
    q.put(1)
    q.put(2)
    q.put(3)
    q.put(4)
    结果为
    C:pycharmpython.exe D:/python练习程序/第三十七天/practise.py
    
    Process finished with exit code 0
    View Code

      放入的元素超过了自己设置的容器容量:程序会进入堵塞状态,如果程序中队列元素已经去玩,再去get则也会进入堵塞状态

    from multiprocessing import Queue
    q=Queue(4)#实例化一个队列对象,并设置容器大小
    q.put(1)
    q.put(2)
    print(q.full())
    q.put(3)
    q.put(4)
    print(q.full())#判断容器是否已经装满
    结果为
    False
    True
    View Code
    from multiprocessing import Queue
    q=Queue(4)#实例化一个队列对象,并设置容器大小
    q.put(1)
    q.put(2)
    print(q.full())
    q.put(3)
    q.put(4)
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.empty())#用于判断队列中元素是否已经取完
    结果为
    False
    1
    2
    3
    4
    View Code

    5. q.get()方法:

    返回q中的一个项目,如果q为空,此方法则进入堵塞状态,直到队列中项目可用为止。block用于控制阻塞行为,默认为True

    6.q.put()

    将item放入到队列中,如果队列已经满了,此方法将堵塞至空间可以用为止。

    7.队列的作用主要适用于进程于进程之间进行数据通讯的:

      1.主进程和子进程之间的通讯:

    from multiprocessing import Process,Queue
    def func(q):
        q.put('hello')
    if __name__=='__main__':
        q=Queue()
        p=Process(target=func,args=(q,))
        p.start()
        print(q.get())#通过队列可以进行子进行和主进程之间数据交流
    结果为
    hello
    View Code

      2.子进程与子进程之间的通讯:

    from multiprocessing import Process,Queue
    def procuder(q):
        q.put('hello') #进行数据的存储
    def user(q):
        print(q.get()) #进行数据的获取
    if __name__=='__main__':
        q=Queue()
        p=Process(target=procuder,args=(q,))
        p.start()
        p1=Process(target=user,args=(q,))
        p1.start()
    结果为
    hello
    View Code

    8.包子机制

    1.一般对数据处理会有两个过程:

     2.生产包子程序:

    from multiprocessing import Process,Queue
    import time
    def procuder(name,food,q):
        for i in range(10):
            time.sleep(1)
            production='%s制造了第%s个%s'%(name,i,food)
            q.put(production)
            print(production)
    if __name__=='__main__':
        q=Queue(30)
        p=Process(target=procuder,args=('alex','包子',q))
        p.start()
        p1=Process(target=procuder,args=(('xiaohong','面包',q)))
        p1.start()
    结果为
    C:pycharmpython.exe D:/python练习程序/第三十七天/practise.py
    alex制造了第0个包子
    xiaohong制造了第0个面包
    alex制造了第1个包子
    xiaohong制造了第1个面包
    xiaohong制造了第2个面包
    alex制造了第2个包子
    xiaohong制造了第3个面包
    alex制造了第3个包子
    xiaohong制造了第4个面包
    alex制造了第4个包子
    xiaohong制造了第5个面包
    alex制造了第5个包子
    alex制造了第6个包子
    xiaohong制造了第6个面包
    alex制造了第7个包子
    xiaohong制造了第7个面包
    alex制造了第8个包子
    xiaohong制造了第8个面包
    xiaohong制造了第9个面包
    alex制造了第9个包子
    View Code

    3.吃包子过程:

    from multiprocessing import Process,Queue
    import time
    import random
    def procuder(name,food,q):
        for i in range(10):
            time.sleep(1)
            production='%s制造了第%s个%s'%(name,i,food)
            q.put(production)
            print(production)
    def eat(name,q):
        while True:
            time.sleep(random.randint(1,4))
            msg=q.get()
            print('%s吃了%s'%(name,msg))
    if __name__=='__main__':
        q=Queue(30)
        p=Process(target=procuder,args=('alex','包子',q))
        p.start()
        p1=Process(target=procuder,args=(('xiaohong','面包',q)))
        p1.start()
        p2=Process(target=eat,args=(('sir',q)))
        p2.start()
    结果为
    ir吃了alex制造了第0个包子
    xiaohong制造了第5个面包
    alex制造了第5个包子
    xiaohong制造了第6个面包
    alex制造了第6个包子
    xiaohong制造了第7个面包
    alex制造了第7个包子
    sir吃了xiaohong制造了第1个面包
    xiaohong制造了第8个面包
    alex制造了第8个包子
    xiaohong制造了第9个面包
    alex制造了第9个包子
    sir吃了alex制造了第1个包子
    sir吃了xiaohong制造了第2个面包
    sir吃了alex制造了第2个包子
    sir吃了xiaohong制造了第3个面包
    sir吃了alex制造了第3个包子
    sir吃了xiaohong制造了第4个面包
    sir吃了alex制造了第4个包子
    sir吃了xiaohong制造了第5个面包
    sir吃了alex制造了第5个包子
    sir吃了xiaohong制造了第6个面包
    sir吃了alex制造了第6个包子
    sir吃了xiaohong制造了第7个面包
    sir吃了alex制造了第7个包子
    sir吃了xiaohong制造了第8个面包
    sir吃了alex制造了第8个包子
    sir吃了xiaohong制造了第9个面包
    sir吃了alex制造了第9个包子
    View Code

    通过结果我们可以看出包子生产完成之后,sir一直在吃,没有办法进行终止,而且吃完所有包子以后进入堵塞状态,这种现象应该怎么解决:

      第一种方法使用q.empty进行判断但是发现解决还是没有办法进行终止:

    from multiprocessing import Process,Queue
    import time
    import random
    def procuder(name,food,q):
        for i in range(10):
            time.sleep(1)
            production='%s制造了第%s个%s'%(name,i,food)
            q.put(production)
            print(production)
            if q.empty==True:
                break
    def eat(name,q):
        while True:
            time.sleep(random.randint(1,2))
            msg=q.get()
            print('%s吃了%s'%(name,msg))
    if __name__=='__main__':
        q=Queue(30)
        p=Process(target=procuder,args=('alex','包子',q))
        p.start()
        p1=Process(target=procuder,args=(('xiaohong','面包',q)))
        p1.start()
        p2=Process(target=eat,args=(('sir',q)))
        p2.start()
        p3=Process(target=eat,args=(('lao',q)))
        p3.start()
    View Code

       第二种方法:使用joinableQueue

    from multiprocessing import Process,JoinableQueue
    import time
    import random
    def procuder(name,food,q):
        for i in range(10):
            time.sleep(1)
            production='%s制造了第%s个%s'%(name,i,food)
            q.put(production)
            print(production)
        q.join()#感知一个队列的数据,全部被执行完毕结束
    def eat(name,q):
        while True:
            time.sleep(random.randint(1,2))
            msg=q.get()
            print('%s吃了%s'%(name,msg))
            q.task_done() #没执行玩一次进行计数减一
    if __name__=='__main__':
        q=JoinableQueue(30)
        p=Process(target=procuder,args=('alex','包子',q))
        p.start()
        p1=Process(target=procuder,args=(('xiaohong','面包',q)))
        p1.start()
        p2=Process(target=eat,args=(('sir',q)))
        p2.daemon=True#设置此进程为守护进程,当主程序结束时,子进程结束
        p2.start()
        p3=Process(target=eat,args=(('lao',q)))
        p3.daemon=True
        p3.start()
        p.join() #感知一个子进程的结束
        p1.join()
    View Code

    结果为

     执行过程如下:

    在生产者这一端:
        每一次生产一个数据,
        且每一次生产的数据都要放在队列中
        在队列中刻上一个记号
        当生产者全部生产完毕以后
        join信号,已经停止生产数据,开始等待数据的使用完毕处理结束完之前都属于堵塞状态
    之后数据处理结束后join'堵塞状态结束
    消费者这一端的程序:
    consumer中把所有的任务都消耗完成
    皮绒促的人端的join感知到,停止堵塞
    所有的prodecuer进程结束
    主进程代码结束
    守护进程也结束
    View Code

  • 相关阅读:
    关于浏览器cookie的详解
    浏览器渲染帧
    Vue3中关于diff的优化
    JS报错 Cannot set property 'display' of undefined问题
    vue选项卡 ,循环数据点击改变class,并初始循环中的第一个为选中状态class
    Nuxt中引入elementUI
    jq 获取节点 改变元素class的显示、隐藏
    vue监听滚动条
    Nuxt中引入iconfont图标
    vue导航点击切换 2.0
  • 原文地址:https://www.cnblogs.com/ab461087603/p/12487582.html
Copyright © 2011-2022 走看看