zoukankan      html  css  js  c++  java
  • day 32

    守护进程

    进程是一个正在运行的程序,守护进程也是一个普通程序,从字面意思可以理解为一个程序可以守护另外一个进程。
    例如古代皇帝有一群妃子,个个娇艳欲滴,享受荣华富贵,但是当皇帝驾崩时,新皇帝是不能继承这些妃子的,因为要作为陪葬品,随先帝而去。

    这里妃子就相当于皇帝的守护者,随着皇帝死亡而结束自己的生命。而在程序中也是如此,如果b进程是a程序的守护进程,那么当a进程结束之后

    b进程也会随之结束,这就是守护进程的含义,在实例化Process对象后调用'p.daemon =  True'即可生成守护进程。

    from multiprocessing import Process
    import time
    
    # 妃子的一生
    def task():
        print("入宫了.....")
        time.sleep(50)
        print("妃子病逝了......")
    
    
    if __name__ == '__main__':
        # 康熙登基了
        print("登基了.....")
    
        # 找了一个妃子
        p = Process(target=task)
    
        # 设置为守护进程 必须在开启前就设置好
        p.daemon = True       #设定好守护进程的标志
        p.start()
    
        # 康熙驾崩了
        time.sleep(3)
        print("故事结束了!")     当父进程关闭以后,守护进程不管有没有走完下面的代码并不会接着往下走,随着结束掉

    互斥锁

    互斥锁是指在多个进程同时运行的时候在抢用cpu进行程序处理时候出现错乱,最终的打印结果会比较糟糕。

    
    
    def task1():
        #使用就上锁,不要对同一把索使用多次acquire,使用一次对应一次release
        # lock.acquire()
        print('我好帅')
        time.sleep(random.randint(0,3))
        print('阿花真美')
        # lock.release()
    
    
    def task2():
        # lock.acquire()
        print('我好帅')
        time.sleep(random.randint(0, 3))
        print('阿芳真美')
        # lock.release()
    #
    #
    #
    #
    if __name__ == '__main__':
        # lock = Lock()
        p1 = Process(target=task1)

    打印结果

    D:python36python.exe "D:/代码文件夹/day 35/开发安全.py"
    我好帅
    我好帅
    阿芳真美
    阿花真美



    可以看出多进程在同时运行的时候出现了抢占cpu的情况,使得打印结果,并不是我们所想要的,这时候只要一把互斥锁就可以解决这个问题了。

    def task1(lock):
        #使用就上锁,不要对同一把索使用多次acquire,使用一次对应一次release
        lock.acquire()   #上锁
        print('我好帅')
        time.sleep(random.randint(0,3))
        print('阿花真美')
        lock.release()    #解锁
    
    
    def task2(lock):
        lock.acquire()          #上锁
        print('我好帅')
        time.sleep(random.randint(0, 3))
        print('阿芳真美')
        lock.release()        #解锁
    #
    #
    #
    #
    if __name__ == '__main__':
        lock = Lock()     #让进程使用同一把互斥锁
        p1 = Process(target=task1,args=(lock,))
        p2 = Process(target=task2,args=(lock,))
    #
    #
    
        p1.start()
        p2.start()

    互斥锁并不是真的把资源给锁了起来,只是当有一个进程先站住之后,在代码层面进行限制,在该进程没有结束操作之前不让其他进程进行操作。

    在程度上来说join函数,也可以解决并行数据错乱的问题,只是他与互斥锁最大的区别是:join 是完全将并发任务变成了串行,这样虽然解决了数据错乱的

    问题,但是原本的并发的高效率,也被随之丢弃,进程的执行顺序会被固定,父进程在子进程没有结束的情况下只能等着。而互斥锁则是会保证原有进程同时并发,父进程可以去执行其他任务,锁任意位置的代码,锁一行都可以。

    IPC

    ipc是指进程间的通讯,进程之间的内存是相互隔离的,大概一个进程的数据想要传给另外一个进程时,大范围上有以下几种方式:管道,文件,socket,和共享内存。

    管道只能实现单方面通讯,数据还都是二进制。

    文件实在硬盘上创建共享文件,优点是几乎不受数据大小的影响,缺点是速度慢。

    socket对编程的复杂度较高。

    共享内存必须由操作系统来分配,优点是传输速度快,缺点就是数据量不能太大。

    共享内存的方式

    Manager类 了解

    Manager提供了许多数据结构,如:list,dict具备进程间共享的特点。

    from multiprocessing import Process,Manager,Lock
    import time
    
    
    def task(data,l):
        l.acquire()
        num = data["num"] #
        time.sleep(0.1)
        data["num"] = num - 1
        l.release()
    
    if __name__ == '__main__':
        # 让Manager开启一个共享的字典
        m = Manager()
        data = m.dict({"num":10})      
    
        l = Lock()
    
        for i in range(10):
            p = Process(target=task,args=(data,l))
            p.start()
    
        time.sleep(2)  这里必须有一个睡眠操作,所有的子进程在处理数据需要时间,这时候如果没有时间间隔的话,直接打印就会出错,所以要有一个时间间隔
                等数据都处理完之后在进行打印
    print(data)

    需要注意的是Manager创建的一些数据结构是不带互斥锁的,所以可能会出现一些问题。

    Queue队列

    队里额是一种特殊的数据结构,先存进去的,取出的时候就取出,区别于堆栈的先存进去的后取出来。

    在导入Queue后,实例化对象时有一个参数maxsize如果我们不指定,那么存储的数量就没有限制。

    from multiprocessing import Queue
    # 创建队列  不指定maxsize 则没有数量限制
    q = Queue(3)
    # 存储元素
    # q.put("abc")
    # q.put("hhh")
    # q.put("kkk")
    
    # print(q.get())
    # q.put("ooo")    # 如果容量已经满了,在调用put时将进入阻塞状态 直到有人从队列中拿走数据有空位置 才会继续执行
    
    #取出元素
    # print(q.get())# 如果队列已经空了,在调用get时将进入阻塞状态 直到有人从存储了新的数据到队列中 才会继续
    
    # print(q.get())
    # print(q.get())

    还有一些常用的方法

    #block 表示是否阻塞 默认是阻塞的   # 当设置为False 并且队列为空时 抛出异常
    q.get(block=True,timeout=2)
    # block 表示是否阻塞 默认是阻塞的   # 当设置为False 并且队列满了时 抛出异常
    # q.put("123",block=False,)
    # timeout 表示阻塞的超时时间 ,超过时间还是没有值或还是没位置则抛出异常  仅在block为True有效

    生产者消费者模型

    首先模型就是解决某个问题的套路,生产数据的一方称为生产者,处理数据的一边就是消费者。假如我们去饭店吃饭,厨师就是生产者,我们就是消费者。

    但是生产者与消费者的往往步调不一样,就会出现一方在等一方的情况。

     

    解决方案:将两者直接分开,各自去完成自己需要完成的任务,为了能实现数据之间的交互,在两者之间创建一个共享内存,生产者将完成后的数据存储

    到共享内存中,消费者则在需要数据的时候去共享内存中取出来就可以了。这样两边就可以互不影响。

    def eat(q):
        for i in range(10):
            # 要消费
            rose = q.get()
            time.sleep(random.randint(0, 2))     
            print(rose,"吃完了!")
    
    # 生产任务
    def make_rose(q):
        for i in range(10):
            # 再生产
            time.sleep(random.randint(0, 2))
            print("第%s盘青椒肉丝制作完成!" % i)
            rose = "第%s盘青椒肉丝" % i
            # 将生成完成的数据放入队列中
            q.put(rose)
    
    if __name__ == '__main__':
        # 创建一个共享队列
        q = Queue()
        make_p = Process(target=make_rose,args=(q,))
        eat_p =  Process(target=eat,args=(q,))
    
    
        make_p.start()
        eat_p.start()
  • 相关阅读:
    对象o o[name]和o['name']的差别
    数组转换为字符串
    函数和方法区别
    创建对象和构造函数的区别
    jQuery光源移动效果
    继承原型链
    javascript跨域
    prototype、constructor、__proto__
    寄生组合式继承
    组合继承
  • 原文地址:https://www.cnblogs.com/1624413646hxy/p/10969419.html
Copyright © 2011-2022 走看看