zoukankan      html  css  js  c++  java
  • 进程之间的通信(IPC),对列,管道,数据共享.进程池初识

    进程之间的通信:

    1. 对列

    2. 管道

    进程之间的数据共享

    进程池

    对列 先进先出FIFO ---维护秩序的时候用的比较多 买票  秒杀

    from  queue  import  Queue

    q = Queue(5)  #括号里面的数字是设置队列的长度

    print(q.qsize())  #查看队列的当前长度

    q.put(12)    #向队列中添加内容

    q.get()      #取出内容

    当队列中满了或者空了,再去填值或者取值就会阻塞.

    print(q.full())  #查看队列是否满了

    print(q.empty())  #查看队列是否空了

    q.put_nowait(4)  #如果队列满了继续放值,则会报错.

    q.get_nowait()  #如果队列空了继续取值,则会报错.

    栈 : 先进后出  ----算法

    实例 : 三级菜单

    计算文件夹的总大小

    进程之间的通信  ---  IPC

    队列

    from multiprocessing import Queue

    q = Queue()

    在多进程中 q.qsize() q.empty()  q.full()是不准的

    q.empty()

    q.full()

    q.put_nowait()

    q.put()

    q.get()

    q.get_nowait()

    q.qsize()

    主进程放  子进程取

    from multiprocessing import Queue , Process

    def con(q):

      print(q.get())

    if __name__ == "__main__":

      q = Queue()

      p = Process(target=con,args=(q,))

      p.start()

      q.put(123)

    子进程放  另一个子进程取

    from multiprocessing import Queue , Process

    def con(q):

      print(q.get())

    def pro(q):

      q.put(123)

    if __name__ == "__main__":

      q = Queue()

      p = Process(target=con,args=(q,))

      p.start()

      c = Process(target=pro,args=(q,))

      c.start()

    生产者消费者模型 -- 解决创造(生产)数据和处理(消费)数据的效率不平衡问题

    把创造数据和处理数据放在不同的进程中 , 根据他们的效率来调整进程的个数

    生产数据快 消费数据慢  内存空间的浪费

    消费数据快  生产数据慢  效率低下

    import time,random

    from multiprocessing import Process,Queue

    def consumer(q,name):

      while True:

        food = q.get()

        if food == "stop" : break

        print("%s  消费了 %s"%(name,food))

        time.sleep(random.random())

    def product(q,name,food,n = 10):

      for i in range(n):

        time.sleep(random.random())

        fd = food + str(i)

        print("%s 生产了%s"%(name,fd))

        q.put(fd)

    if __name__ == "__main__":

      q = Queue()

      c = Process(target=consumer,args=(q,"alex""))

      c.start()

      p = Process(target=product,args=(q,"egon","美女")

      p.start()

      p.join()

      q.put("stop")

    让consumer停下来的方法

      1.在所有生产者结束生产之后向队列中放入一个结束符

      2.有几个consumer就向队列中放几个结束符

      3.在消费之消费的过程中,接收到结束符,就结束消费的进程

    import time,random

    from multiprocessing import JoinableQueue , Process

    def consumer(q,name):

      while True:

        food = q.get()

        print("%s 吃了%s"%(name,food))

        time.sleep(random.random())

        q.task_done()

    def product(q,name,food,n= 10):

      for i in range(10):

        time.sleep(random.random())

        fd = food + str(i)

        print("%s 生产了%s"%(name,fd))

        q.put(fd)

      q.join(()

    if __name__ == "__main__":

      q = JoinableQueue()

      p = Process(target=product,args=(q,"egon","美女"))

      p.start()

      c = Process(target=consumer,args=(q,"alex"))

      c.daemon = True

      c.start()

    只有multiprocessing中的对列,才能帮助实现IPC

    永远不可能出现数据不安全的情况,多个进程不会同时取走同一个数据

    由于对列先进先出的特点 + 进程通信的功能 + 数据进程安全,经常用它来完成进城之间的通信

    生产者消费者模型:

    生产者和消费者的效率平衡的问题

    内存的控制 -- 对列的长度限制

    让消费者自动停下来

    JoinableQueue

    在消费数据的时候 : task_done

    在生产端主进程 : join

    管道 : 是IPC通信的一种机制,队列就是基于管道来完成通信的,但是管道是原生的通信方式,在进程之间会产生数据不安全的情况,需要自己手动加锁来处理.管道在数据传输过程中,还涉及到一个端口管理这个需要我们在代码中处理,才能使代码更完善.

    队列就是基于管道实现的

    对列 : 数据是安全的

    管道 : 数据是不安全的

    对列 = 管道 + 锁

    from multiprocessing import Pipe

    left ,right = Pipe()

    left.send("hello")

    print(right.recv())

    from multiprocessing import Pipe,Process

    def consumer(left,right):

      left.close()

      while 1:

        try:

          print(right.recv())

        except EOFError:

          break

    if __name__ == "__main__":

      left,right  = Queue()

      p = Process(target=consumer,args=(left,right))

      p.start()

      right.close()

      for i in range(5):

        left.send("hello")

      left.close()

    EOF异常的出发:

    在这一个进程中如果不在用这个端点了,应该close

    这样在recv的时候,如果其他端点都被关闭了,就能够知道不会再有新的消息传进来,此时就不会在这里阻塞等待,而是抛出一个EOFError

    close并不是关闭了整个管道,而是修改了操作系统对管道端点的应用计数的处理

    from multiprocessing Process,Pipe

    def consumer(p,name):

      left,right = p

      left.close()

      while 1:

        try:

          ba = right.recv()

        except EOFError:

          break

    def product(p,seq=10):

      left,right = p

      right.close()

      for i in range(seq):

        left.send("hello")

    if __name__ == "__main__":

      left,right=Pipe()

      for i in range(5):

        p = Process(target=consumer,args=((left,right),"nana"))

        p.start()

      for i in range(5):

        c = Process(target=product,args=((left,right),))

        c.start()

      left.close()

      right.close()

    6.数据共享 : Manager模块

    from multiprocessing import Manager,Process,Lock

    def work(d,lock):

      with lock:

        d["count"] -= 1

    if __name__ == "__main__":

      lock = Lock()

      m = Manager()  #共享数据

      dic = m.dict({"count":100})  #Manager调用字典

      pl = []

      for i in range(100):

        p = Process(target=work,args=(dic,lock))  #所有子进程共享字典

        pl.append(p)

        p.start()

      for i in pl:

        i.join()

      print(dic)

    7.进程池的初识:

    操作系统开启进程慢,几个CPU就能同时运行几个进程,进程的个数不是无限开启的

    进程池 : 如果必须用多个进程,且是高计算性,没有IO型的程序,希望并行,最充分的使用CPU.

    import os,time

    from multiprocessing import Pool

    def func(i):

      time.sleep(0.1)

      print(os.getpid(),i)

    if __name__== "__main__":

      p = Pool(5)

      for i in range(20):

        p.apply_async(func,args=(i,))

      p.close()

      p.join()

    8.总结:

    IPC通信:

    队列 : 管道 + 锁

    管道 : 是队列的底层

    数据共享 : 进程就是数据隔离的

    Manager模块

    数据类型都能够进行数据共享

    一部分都是不加锁,不支持数据进程安全

    不安全的解决办法 是加锁

    进程池

    进程不能无限开,会给操作系统调度增加负担

    且真正能被同时执行的进程最多也就和CPU个数相同等

    进程的开启和销毁都要消耗资源和时间

    进程池 和信号量 :

    进程池 :

    进程池里有几个进程,就起几个.不管多少任务,池子里进程的个数是固定的.

    开启进程和关闭进程这些事都是需要固定的时间开销 , 不会产生额外的时间开销 ; 且进程池中的进程数控制的好,那么操作系统的压力也小.

    信号量 : 

    有多少个任务就起多少个进程/线程

    可以帮助减少操作系统切换负担 , 但是并不能帮助减少进/线程开启和关闭的时间

        

  • 相关阅读:
    Win32中精确计时器(微秒级)
    一个封装文件操作和目录操作的类
    CString
    两个经典的RGB与YUV转换函数
    C++文件流
    HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型
    MPEG4与H264区别,编码及应用
    C file文件基本知识
    RGB ,YUV, YCbCr的定义
    在android平台上测试C/C++程序及库
  • 原文地址:https://www.cnblogs.com/fengkun125/p/9378707.html
Copyright © 2011-2022 走看看