zoukankan      html  css  js  c++  java
  • day34——僵尸进程和孤儿进程、互斥锁、进程之间的通信

    day34

    僵尸进程和孤儿进程

    基于unix环境(linux,macOS)

    • 主进程需要等待子进程结束之后,主进程才结束

      主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收

    • 为什么主进程不在子进程结束后马上对其回收呢?

      • 主进程与子进程是异步关系,主进程无法马上捕获进程什么时候结束
      • 如果子进程结束之后马上在内存中释放资源,主进程就没有办法监测子进程的状态了
    • unix针对于上面的问题,提供了一个机制

      所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容,(进程号,结束时间,运行状态),等待主进程监测回收

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

    • 僵尸进程有无危害?

      如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号

    • 孤儿进程

      • 父进程由于某种原因结束了,但是子进程还在运行中,这些子进程就成了孤儿进程。
      • 父进程如果结束了,所有的孤儿进程就会被init进程回收,init就会变成父进程,对其进行回收
    • 僵尸进程如何解决?

      父进程产生了大量进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程,由init进程回收

    互斥锁

    定义:互斥锁就是在保证子进程串行的同时,也保证了子进程执行顺序的随机性,以及数据的安全性

    lock与join的区别

    共同点:都可以把并发变成串行,保证了顺序

    不同点:join人为设定顺序,lock让其争抢顺序,保证了公平性

    三个同事 同时用一个打印机打印内容
    三个进程模拟三个同事,输出平台模拟打印机
    
    # 版本一
    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",))
    
        p1.start()
        p1.join()
        p1.start()
        p1.join()
        p1.start()
        p1.join()
    
    # 我们利用join解决串行的问题,保证了顺序优先,但是这个谁先谁后时固定的
    # 这样不合理,你在争抢同一个资源的时候,应该时先到先得,保证公平
    
    
    # 版本三
    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    import random
    import os
    
    
    def task1(p, lock):
        # lock.acquire() 不可重复使用,会导致阻塞
        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()
    
    
    def task4(p, lock):
        lock.acquire()
        print(f"{p}开始打印了")
        time.sleep(random.randint(1,3))
        print(f"{p}打印结束了")
        lock.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        p1 = Process(target=task1, args=("p1", mutex))
        p2 = Process(target=task2, args=("p2", mutex))
        p3 = Process(target=task3, args=("p3", mutex))
        p4 = Process(target=task4, args=("p4", mutex))
    
        p1.start()
        p2.start()
        p3.start()
        p4.start()
    

    进程之间的通信

    基于文件通信

    进程在内存级别是隔离的,但是文件在磁盘上不是

    利用抢票系统讲解

    缺点:

    • 效率低
    • 自己加锁麻烦而且很容易出现死锁
    抢票系统
    1、先可以查票,查询余票数,并发
    2、进行购买,向服务端发送请求,服务端接收请求,在后端将票数-1,返回到前端,串行
    
    from multiprocessing import Process
    from multiprocessing import Lock
    import random
    import json
    import os
    import time
    
    
    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(lock):
        with open("ticket.json", encoding="utf-8")as f:
            dic = json.load(f)
        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()
        paid()
    
    
    if __name__ == '__main__':
        for i in range(5):
            p = Process(target=task)
            p.start()
    当多个进程共抢一个数据时,如果要保证数据的安全,必须要串行
    要想让购买环节进行串行,我们必须要加锁处理
    
    from multiprocessing import Process
    from multiprocessing import Lock
    import random
    import json
    import os
    import time
    
    
    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(lock):
        # lock.acquire()
        with open("ticket.json", encoding="utf-8")as f:
            dic = json.load(f)
        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()}购买成功")
        # lock.release()
    
    
    def task(lock):
        search()
        lock.acquire()
        paid(lock)
        lock.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(15):
            p = Process(target=task, args=(mutex,))
            p.start()
    当很多进程共抢一个资源(数据)时,你要保证顺序(数据的安全),一定要串行
    互斥锁:可以公平性的保证顺序以及数据的安全
    
    基于队列通信

    队列:把队列理解成一个容器,这个容器可以承载一些数据

    队列的特性:先进先出永远保持这个数据。——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())
    q.get()()
    
    • 特性
    from multiprocessing import Queue
    q = Queue(4)  # 可以设置队列最大长度(maxsize)
    
    
    def func():
        print("in func")
    
    
    q.put(1)
    q.put("alex")
    q.put([1, 2, 3])
    q.put(func)
    q.put(555,block=False)  # 当队列满了时,在进程put数据就会阻塞,如果block=False就会报错而不是阻塞
    
    print(q.get())
    print(q.get())
    print(q.get(timeout = 3))  # 阻塞3秒,3秒之后还阻塞直接报错
    q.get()()
    print(q.get(block=False))  # 当数据取完时,在进程get数据也会出现阻塞,直到某个进程put数据。如果block=False就会报错而不是阻塞
    
    基于管道通信
  • 相关阅读:
    jQuery.fly插件实现添加购物车抛物线效果
    jQuery 实现前端模糊匹配与首字母搜索
    Java生成微信二维码及logo二维码
    Map 与 JavaBean 的相互装换
    从零写Java Web框架——请求的处理DispatcherServlet
    从零写Java Web框架——实现Ioc依赖注入
    记一次校招面试
    使用DbUtils对JDBC封装实现面向实体查询
    HTTP Status 500 PWC6188 jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
    【插件】百度编译器ueditor插入视频的时候。在预览的窗口提示 “输入的视频地址有误,请检查后再试!
  • 原文地址:https://www.cnblogs.com/NiceSnake/p/11432169.html
Copyright © 2011-2022 走看看