zoukankan      html  css  js  c++  java
  • 僵尸进程,孤儿进程,以及队列认知

    1. 僵尸进程和孤儿进程(基于UNIX环境:linux,macos)

      1. 僵尸进程:所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态

        1. 主进程需要等待子进程结束之后,主进程才结束
        2. 主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内将子进程进行回收
        
        from multiprocessing import Process
        import time
        import os
        def task(name):
            print(f'{name} is running')
            print(f'主进程:{os.getppid()}')
            print(f'子进程:{os.getpid()}')
            time.sleep(50)
            print(f'{name} is gone')
        
        if __name__ == '__main__':
            p = Process(target=task,args=('长兴',))
            p.start()
            print('===主开始')
        主进程等待子进程结束之后,主进程结束
        
        1. 为什么主进程不在子进程结束后马上对其回收呢
        1.主进程和子进程是异步关系,主进程无法马上捕获子进程什么时候结束
        2.如果子进程结束之后马上在内存中释放资源,主进程就没有办法监测子进程的状态了
        
        1. Unix针对上面的问题,提供了一个机制
        所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容:进程号,结束时间,运行状态,等待主进程监测,回收 
        
        1. 僵尸进程的危害
        如果父进程不对僵尸进程进行回收(wait、waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号
        
      2. 孤儿进程:

        父进程由于某种原因结束了,但是你的子进程还在运行中,这样你的这些子进程就成了孤儿进程,你的父进程如果结束了,你的所有孤儿进程就会被init进程回收,init就会变成你的父进程,对子进程进行回收。
        
        1. 僵尸进程如何解决?
        父进程产生了大量的子进程,但是不回收,这样就会形成大量的僵尸进程,解决方法就是直接杀死父进程,将所有的僵尸进程变成孤儿进程,由init进行回收
        
    2. 互斥锁

      举例: 三个同事,同时用一个打印机打印内容

      ​ 三个进程模拟三个同事,输出平台模拟打印机

      # 版本一:
      # from multiprocessing import Process
      # import time
      # import random
      # import os
      #
      # def task1():
      #     print(f'{os.getpid()}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{os.getpid()}打印结束了')
      #
      # def task2():
      #     print(f'{os.getpid()}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{os.getpid()}打印结束了')
      #
      # def task3():
      #     print(f'{os.getpid()}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{os.getpid()}打印结束了')
      #
      # if __name__ == '__main__':
      #
      #     p1 = Process(target=task1)
      #     p2 = Process(target=task2)
      #     p3 = Process(target=task3)
      #
      #     p1.start()
      #     p2.start()
      #     p3.start()
      
      # 现在是所有的进程都并发的抢占打印机,
      # 并发是以效率优先的,但是目前我们的需求: 顺序优先.
      # 多个进程共强一个资源时, 要保证顺序优先: 串行,一个一个来.
      
      
      # 版本二:
      
      
      # from multiprocessing import Process
      # import time
      # import random
      # import os
      #
      # def task1(p):
      #     print(f'{p}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{p}打印结束了')
      #
      # def task2(p):
      #     print(f'{p}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{p}打印结束了')
      #
      # def task3(p):
      #     print(f'{p}开始打印了')
      #     time.sleep(random.randint(1,3))
      #     print(f'{p}打印结束了')
      #
      # if __name__ == '__main__':
      #
      #     p1 = Process(target=task1,args=('p1',))
      #     p2 = Process(target=task2,args=('p2',))
      #     p3 = Process(target=task3,args=('p3',))
      #
      #     p2.start()
      #     p2.join()
      #     p1.start()
      #     p1.join()
      #     p3.start()
      #     p3.join()
      
      # 我们利用join 解决串行的问题,保证了顺序优先,但是这个谁先谁后是固定的.
      # 这样不合理. 你在争抢同一个资源的时候,应该是先到先得,保证公平.
      
      
      版本三:
      from multiprocessing import Process
      from multiprocessing import Lock
      import time
      import sys
      import random
      
      def task1(p,lock):
      	lock.acquire()
      	print(f'{p}打印开始了')
      	time.sleep(random.randint(1,3))
      	print(f'{p}打印结束了')
      	lock.release()
      
      def task2(p,lock):
      	lock.acquire()
      	print(f'{p}打印开始了')
      	time.sleep(random.randint(1,3))
      	print(f'{p}打印结束了')
      	lock.release()
      
      def task3(p,lock):
      	lock.acquire()
      	print(f'{p}打印开始了')
      	time.sleep(random.randint(1,3))
      	print(f'{p}打印结束了')
      	lock.release()
      
      if __name__ =='__main__':
      	mutex = Lock()
      	for i in range(1,4):
      		p = Process(target = getattr(sys,modules[__name__],f'task{i}'),args = (f'p{i}',mutex))
      		p.start()
      
      1. lock和join的区别
      共同点:都可以把并发变成串行,保证了顺序
      不同点:join人为设定顺序,lock让其争抢顺序,保证了公平性
      
    3. 进程之间的通信

      1. 基于文件的通信

        抢票系统.
        # 1. 先可以查票.查询余票数.  并发
        # 2. 进行购买,向服务端发送请求,服务端接收请求,在后端将票数-1,返回到前端. 串行.
        
        # from multiprocessing import Process
        # import json
        # import time
        # import os
        # import random
        #
        #
        # def search():
        #     time.sleep(random.randint(1,3))  # 模拟网络延迟(查询环节)
        #     with open('ticket.json',encoding='utf-8') as f1:
        #         dic = json.load(f1)
        #         print(f'{os.getpid()} 查看了票数,剩余{dic["count"]}')
        #
        #
        # def paid():
        #     with open('ticket.json', encoding='utf-8') as f1:
        #         dic = json.load(f1)
        #     if dic['count'] > 0:
        #         dic['count'] -= 1
        #         time.sleep(random.randint(1,3))  # 模拟网络延迟(购买环节)
        #         with open('ticket.json', encoding='utf-8',mode='w') as f1:
        #             json.dump(dic,f1)
        #         print(f'{os.getpid()} 购买成功')
        #
        # def task():
        #     search()
        #     paid()
        #
        #
        # if __name__ == '__main__':
        #
        #     for i in range(6):
        #         p = Process(target=task)
        #         p.start()
        
        # 当多个进程共强一个数据时,如果要保证数据的安全,必须要串行.
        # 要想让购买环节进行串行,我们必须要加锁处理.
        
        #
        # from multiprocessing import Process
        # from multiprocessing import Lock
        # import json
        # import time
        # import os
        # import random
        #
        #
        # def search():
        #     time.sleep(random.randint(1,3))  # 模拟网络延迟(查询环节)
        #     with open('ticket.json',encoding='utf-8') as f1:
        #         dic = json.load(f1)
        #         print(f'{os.getpid()} 查看了票数,剩余{dic["count"]}')
        #
        #
        # def paid():
        #     with open('ticket.json', encoding='utf-8') as f1:
        #
        #         dic = json.load(f1)
        #     if dic['count'] > 0:
        #         dic['count'] -= 1
        #         time.sleep(random.randint(1,3))  # 模拟网络延迟(购买环节)
        #         with open('ticket.json', encoding='utf-8',mode='w') as f1:
        #             json.dump(dic,f1)
        #         print(f'{os.getpid()} 购买成功')
        #
        #
        # def task(lock):
        #     search()
        #     lock.acquire()
        #     paid()
        #     lock.release()
        #
        # if __name__ == '__main__':
        #     mutex = Lock()
        #     for i in range(6):
        #         p = Process(target=task,args=(mutex,))
        #         p.start()
        
        
        # 当很多进程共强一个资源(数据)时, 你要保证顺序(数据的安全),一定要串行.
        # 互斥锁: 可以公平性的保证顺序以及数据的安全.
        
        # 基于文件的进程之间的通信:
            # 效率低.
            # 自己加锁麻烦而且很容易出现死锁.
        
        # dic = {'name': 'alex'}
        # import json
        # print(json.dumps(dic))
        
      2. 基于队列的通信

        1. 队列:一个可以承载数据的容器,先进先出永远保持这个数据

        2. q = Queue(3) 设置队列里的数据数,满了就会阻塞,当数据取完,在进程get数据也会出现阻塞,直到某一个进程put数据

        3. q.get(timeout = 3) )阻塞3秒,3秒之后还阻塞直接报错

        4. block = False 只要遇到阻塞就会报错

          q.put(555,block = False)
          q.get(block = False)
          
        队列: 把队列理解成一个容器,这个容器可以承载一些数据,
        # 队列的特性: 先进先出永远保持这个数据. FIFO 羽毛球筒.
        # from multiprocessing import Queue
        # q = Queue()
        # def func():
        #     print('in func')
        # q.put(1)
        # q.put('alex')
        # q.put([1,2,3])
        # q.put(func)
        #
        #
        # print(q.get())
        # print(q.get())
        # print(q.get())
        # f = q.get()
        # f()
        
        
        # from multiprocessing import Queue
        # q = Queue(3)
        #
        # q.put(1)
        # q.put('alex')
        # q.put([1,2,3])
        # # q.put(5555)  # 当队列满了时,在进程put数据就会阻塞.
        # # q.get()
        #
        # print(q.get())
        # print(q.get())
        # print(q.get())
        # print(q.get())  # 当数据取完时,在进程get数据也会出现阻塞,直到某一个进程put数据.
        
        
        from multiprocessing import Queue
        q = Queue(3)  # maxsize
        
        q.put(1)
        q.put('alex')
        q.put([1,2,3])
        # q.put(5555,block=False)
        #
        print(q.get())
        print(q.get())
        print(q.get())
        print(q.get(timeout=3))  # 阻塞3秒,3秒之后还阻塞直接报错.
        # print(q.get(block=False))
        
        # block=False 只要遇到阻塞就会报错.
        
        
        # 第一个作业: 将抢票系统变成队列方式完成.
        
        
  • 相关阅读:
    UVA10163 Storage Keepers (动态规划)
    Uva12174 Shuffle(滑动窗口)
    上决╇ф人员分配问题 (背包问题)
    UVA
    UVALive
    poj1151 Atlantis (线段树+扫描线+离散化)
    poj2528 Mayor's posters (线段树+离散化)
    php 调用微信虚拟支付
    ptoto文件转换的java文件,报错 UnusedPrivateParameter
    redis 安装及启动时警告处理
  • 原文地址:https://www.cnblogs.com/-777/p/11391576.html
Copyright © 2011-2022 走看看