zoukankan      html  css  js  c++  java
  • day33 守护进程、互斥锁、进程间通信、生产者消费者模型part1、生产者消费者模型part2、生产者消费者模型part3

    1、守护进程

      守护进程其实就是一个'子进程'

      守护=>伴随

      守护进程会伴随主进程的代码运行完毕后而死掉

    2、为何用守护进程

      关键字就两个"

        进程:

          当父进程需要将一个任务并发出去执行,需要将该任务放到一个子进程里

        守护:

          当该子进程内的代码在父进程代码运行完毕后就没有存在的意义了,就应该将该

        子进程设置为守护进程,会在父进程代码结束后死掉。

    from multiprocessing import Process
    import time,os
    
    def task():
        print('%is running'%os.getpid())  #获得的事进程的pid   ppid查看其父进程的id号
        time.sleep(3)
    
    if __name__=='__main__':
        p=Process(target=task)
        p.daemon=True#一定要放到p.start()之前  p.daemon为其守护进程
        p.start()
        print('主')
        print('%主is running' % os.getpid())
    #如何把一个子进程做成守护进程呢?
    
    #到底是什么场景需要子进程?
    #生产者消费者模型的时候

    互斥锁

    错误1:一张票卖了10次  (购票操作不应该并发,而是应该串行)

    from multiprocessing import Process
    import json
    import os
    import time
    import random
    
    def check():
        time.sleep(random.randint(1,3))#1~3  模拟网络延迟
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count']))  #用多个进程来模拟多个人的
    
    def get():
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        time.sleep(random.randint(1,3))
        if dic['count']>0:
            #有票
            dic['count']-=1
            time.sleep(random.randint(1,3))
            with open('db.txt','wt',encoding='utf-8') as f:
                json.dump(dic,f)
            print('%s购票成功'%os.getpid())
        else:
            print('%s没有余票'%os.getpid())
    
    def task():
        #查票
        check()
        #购票
        get()
    
    if __name__ == '__main__':
        for i in range(10):
            p=Process(target=task)
            p.start()
    
    #db.txt文件
    {"count": 0}

    错误2:查票应该是并发的 购票应该是串行的,保证数据安全的核心是并发编程串行

    from multiprocessing import Process
    import json
    import os
    import time
    import random
    
    def check():
        time.sleep(random.randint(1,3))#1~3  模拟网络延迟
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count']))  #用多个进程来模拟多个人的
    
    def get():
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        time.sleep(random.randint(1,3))
        if dic['count']>0:
            #有票
            dic['count']-=1
            time.sleep(random.randint(1,3))
            with open('db.txt','wt',encoding='utf-8') as f:
                json.dump(dic,f)
            print('%s购票成功'%os.getpid())
        else:
            print('%s没有余票'%os.getpid())
    
    def task():
        #查票
        check()
        #购票
        get()
    
    if __name__ == '__main__':
        for i in range(10):
            p=Process(target=task)
            p.start()
            p.join()
    
    #db.txt文件
    {"count": 0}
    

    正确的方法:加互斥锁:

    from multiprocessing import Process,Lock
    import json
    import os
    import time
    import random
    
    def check():
        time.sleep(random.randint(1,3))#1~3  模拟网络延迟
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count']))  #用多个进程来模拟多个人的
    
    def get():
        with open('db.txt','rt',encoding='utf-8') as f:
            dic=json.load(f)
        time.sleep(random.randint(1,3))
        if dic['count']>0:
            #有票
            dic['count']-=1
            time.sleep(random.randint(1,3))
            with open('db.txt','wt',encoding='utf-8') as f:
                json.dump(dic,f)
            print('%s购票成功'%os.getpid())
        else:
            print('%s没有余票'%os.getpid())
    
    def task(mutex):
        #查票
        check()
    
        #购票
        mutex.acquire()#互斥锁不能连续的acquire,必须是release后才能重新acquire
        get()
        mutex.release()
        # with mutex:#简写版
        #     get()
    if __name__ == '__main__':
        mutex=Lock()
        for i in range(10):
            p=Process(target=task,args=(mutex,))
            p.start()
    #db.txt文件
    # {"count": 0}
    
    
    #互斥锁:将并发变成串行,牺牲了效率保证了数据安全
    

     互斥锁跟之前的join思路一样,都是将并发编程串行。join是真正意义上的穿行 join所有的都串行,join是查票都变成串行了,所以join将要执行的代码编程整体的串行。

    互斥锁:可以将部分代码(只涉及到修改共享数据的代码)变成串行

    join是将执行任务的所有代码整体串行

    进程间通信

    # IPC:进程间通信,有两种实现方式  #inter progress communicate 进程之间交流
    # 1、pipe: #基于管道的
    # 2、queue:pipe+锁 #基于队列的  队列是管道加锁实现的  管道和队列都是为了实现进程之间通信的
    
    from multiprocessing import Queue
    q=Queue(3) #先进先出
    #注意:
    #1、队列占用的是内存空间
    #2、不应该往队列中放大数据,应该只存放数据量较小的消息
    # 掌握的
    q.put('first')
    q.put({'k':'sencond'})
    q.put(['third',])
    q.put(4)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    

     

    之前借助进程之间通信靠文件,文件是硬盘空间

    硬盘的效率太低

    需要另外一种介质来打破内存间介质的通信

    需要一个共享的内存空间

    在linux系统中 free -m查看共享的内存

    进程间的通信应该用内存空间而不是硬盘空间

    生产者消费者模型

    生产者消费者模型
    该模型中包含两类重要的角色:
    1、生产者:将负责造数据的任务比喻为生产者
    2、消费者:接收生产者造出的数据来做进一步的处理,该类人物被比喻成消费者


    实现生产者消费者模型三要素
    1、生产者
    2、消费者
    3、队列

    什么时候用该模型:
    程序中出现明显的两类任何,一类任务是负责生产,另外一类任务是负责处理生产的数据的

    该模型的好处:
    1、实现了生产者与消费者解耦和
    2、平衡了生产力与消费力,即生产者可以一直不停地生产,消费者可以不停地处理,因为二者
    不再直接沟通的,而是跟队列沟通

    import time
    import random
    from multiprocessing import Process,Queue
    
    def consumer(name,q):
        while True:
            res=q.get()
            time.sleep(random.randint(1,3))
            print('33[46m消费者===》%s 吃了 %s33[0m' %(name,res))
    
    
    def producer(name,q,food):
        for i in range(5):
            time.sleep(random.randint(1,2))
            res='%s%s' %(food,i)
            q.put(res)
            print('33[45m生产者者===》%s 生产了 %s33[0m' %(name,res))
    
    
    if __name__ == '__main__':
        #1、共享的盆
        q=Queue()
    
        #2、生产者们
        p1=Process(target=producer,args=('egon',q,'包子'))
        p2=Process(target=producer,args=('刘清政',q,'泔水'))
        p3=Process(target=producer,args=('杨军',q,'米饭'))
    
        #3、消费者们
        c1=Process(target=consumer,args=('alex',q))
        c2=Process(target=consumer,args=('梁书东',q))
    
    
        p1.start()
        p2.start()
        p3.start()
        c1.start()
        c2.start()
    #用爬虫比较好  二期视频补充了很多相关的知识
    

      

  • 相关阅读:
    python3 获取n天后的日期时间
    python3 获取n年前日期
    RequestsDependencyWarning: urllib3 (1.25.2) or chardet (3.0.4) doesn't match a supported version!
    html5 富文本编辑器
    python3 md5 加密
    python3 获取当前日期以及7天后的日期(2016-03-20 11:45:39 形式)
    python3 生成随机手机号
    python 列表 字典转json
    (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')))
    【Python】时间与时间戳
  • 原文地址:https://www.cnblogs.com/wangmiaolu/p/9302951.html
Copyright © 2011-2022 走看看