• 多进程,互斥锁


    守护进程

    • 什么是守护进程

    在python中,守护进程也是一个进程,默认情况下,主进程及时代码执行完毕了也会等待子进程结束才会结束自己,当一个进程B设置为另一个进程A的守护进程时, A是被守护,B是守护进程

    特点是:当被守护A结束时,即使B的任务没有完成也会随之结束

    比喻:

    康熙是一个进程,妃子是康熙的守护进程

    康熙驾崩了,如果妃子还活着,那就陪葬去,当然如果妃子的任务提前结束了那就立即挂了

    **案例

    from multiprocessing import Process
    import time
    
    def task():
        print('zi run')
        time.sleep(3)
        print('zi over')
        
    if __name__=='__main__':
        p = Process(target=task)
        p.daemon = True  # 将这个进程设置为了守护进程  必须在开启进程前设置
        p.start()
        print('主 over')
    

    进程安全问题

    当并发的多个任务是,要同时操作同一个资源,就会造成数据错乱的问题

    解决方法是:将并发操作公共资源的代码由并发转为串行,解决安全问题,但是牺牲了效率

    串行方式1

    直接使用join函数

    缺点:将任务中所有的代码都串行,此时还是不如不要开进程

    多个进程之间原本公平竞争, join是强行规定了执行顺序

    串行方式2,互斥锁(重点)

    原理就是讲要操作的公共资源的代码锁起来,以保证同一时间只能有一个进程在执行这部分代码

    互斥锁是什么

    就是互相排斥的锁

    优点:可以将部分代码串行,同时要注意,必须保证锁只有一把

    使用方式:

    from multiprocessing import Process,Lock
    import time,random
    
    def task1(mutex):
        # 假设这不是访问公共资源 那么还可也并发执行
        for i in range(10000):
            print(1)
    
        mutex.acquire() # 这是加锁
        time.sleep(random.random())
        print("-------name is nick")
        time.sleep(random.random())
        print("-------gender is girl")
        time.sleep(random.random())
        print("-------age is 18")
        mutex.release() # 解锁
        
        
    def task2(mutex):
        for i in range(10000):
            print(2)
    
        mutex.acquire()
        time.sleep(random.random())
        print("++++++++name is bgon")
        time.sleep(random.random())
        print("++++++++gender is oldman")
        time.sleep(random.random())
        print("++++++++age is 48")
        mutex.release()
    
    if __name__ == '__main__':
        mutex = Lock()  # 创建一把互斥锁
        print("创建锁了!!!!")
    
        p1 = Process(target=task1,args=(mutex,))
        p2 = Process(target=task2,args=(mutex,))
    
        p1.start()
        p2.start()
    
    

    加锁 解决了安全问题,带来了效率降低问题

    锁其实只是给执行代码加了限制 本质是一个标志为 True 或 False

    如何使得即保证安全 又提高效率

    锁的 粒度

    粒度指的是被锁住的代码的多少

    粒度越大锁住的越多 效率越低

    互斥锁的案例

    # 抢票
    
    def show():
        with open("db.json") as f:
            data = json.load(f)
            print("剩余票数",data["count"])
    
    def buy():
        with open("db.json") as f:
            data = json.load(f)
            if data["count"] > 0:
                data["count"] -= 1
                with open("db.json","wt") as f2:
                    json.dump(data,f2)
                    print("抢票成功!")
    
    def task(mutex):
        show()
        mutex.acquire()
        buy()
        mutex.release()
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(5):
            p = Process(target=task,args=(mutex,))
            p.start()
            
    

    IPC

    Inter-Process Communication

    空间复用 中内存隔离开了多个进程直接不能直接交互

    IPC指的就是进程间通讯

    几种方式 :

    1.创建一个共享文件

    缺点: 效率较低
    
    优点: 理论上交换的数据量可以非常大  
    
    适用于: 交互不频繁  且数据量较大的情况
    

    2.共享内存 (主要方式)

    缺点: 数据量不能太大  
    
    优点: 效率高 
    
    适用于: 交互频繁,但是数据量小 
    

    3.管道

    管道也是基于文件的    它是单向的   编程比较复杂  
    

    4.socket

    编程复杂,更适用于基于网络来交换数据  
    

    共享内存的第一种方式

    Manger

    可以为我们创建 进程间同步的容器,但是没有处理安全问题 ,所以并不常用

    Queue

    Queue 翻译为队列 是一种特殊的容器 特殊之处在于存取顺序为先进先出

    可以帮我们完成进程间通讯

    from multiprocessing import Queue
    
    q = Queue(2) # 创建队列 并且同时只能存储2个元素
    q.put(1)
    q.put(2)
    
    # q.put(3,block=True,timeout=3) # 默认是阻塞的 当容器中没有位置了就阻塞 直到有人从里面取走元素为止
    print(q.get())
    print(q.get())
    print(q.get(block=True,timeout=3))# 默认是阻塞的 当容器中没有位置了就阻塞 直到有人存入元素为止
    

    扩展: 栈

    也是一种特殊的容器 特殊在于 存取顺序为 先进后出

    函数调用栈

    调用函数时 称之为 函数入栈

    函数执行结束 称之为函数出栈

  • 相关阅读:
    编程之美---求数组中最长递增子序列
    编程之美----子数组的最大乘积
    编程之美----寻找数组中的最大值和最小值
    编程之美---找符合条件的整数
    编程之美----最大公约数问题
    编程之美----1的数目
    编程之美----寻找发帖“水王”
    C语言 |= &= 位运算
    整型数类型定义
    extern使用方法总结!(转)
  • 原文地址:https://www.cnblogs.com/bladecheng/p/11132194.html
Copyright © 2020-2023  润新知