生产者消费者模型,管道,进程之间共享内存,进程池

Posted jerry-hou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生产者消费者模型,管道,进程之间共享内存,进程池相关的知识,希望对你有一定的参考价值。

课程回顾:

  并行:在同一时间点上多个任务同时执行

  并发:在同一时间段上多个任务同时执行

  进程的三大基本状态:

    就绪状态:所有进程需要的资源都获取到了,除了CPU

    执行状态:获取到了所有资源包括CPU,进程处于运行状态

    阻塞状态:程序停滞不在运行,放弃CPU,进程此时处于内存里

  什么叫进程?

    正在运行的程序

    有代码段,数据段,PCB(进程控制块)

  进程是资源分配的基本单位.

  进程之间能不能直接通信?

    正常情况下,多进程之间是无法进行通信的.因为每个进程都有自己独立的空间

  锁: 为了多进程通信时,保护数据的安全性

    一把锁配一把钥匙

    l = Lock()

    l.acquire()

    l.release()

  信号量:

    一把锁配多把钥匙

    sem = Semaphore(num)    ### num 钥匙的数量

  事件:

    e = Event()

    e.is_set()  返回一个bool值

    e.wait()    阻塞和非阻塞

    e.set()    把is_set的bool值变为True

    e.clear()    把is_set的bool值变为False

 

今日内容:

    1.生产者消费者模型

      主要是为解耦

      借助对列来实现生产者消费者模型

      

      栈:先进后出(First In Last Out)    简称:  FILO

      队列:先进先出(First In First Out)   简称:  FIFO

    

    import queue #不能进行多线程之间的数据模型

      (1)from multiprocessing import Queue  借助Queue解决生产者消费者模型

        队列是安全的.

        q = Queue(num)

        #num : 队列的最大长度

        q.get()#阻塞等待获取数据,如果有数据直接获取,如果没有数据,阻塞等待

        q.put()#阻塞,如果可以继续往队列中放数据,就直接放,不能放就阻塞等待

 

        q.get_nowait()#不阻塞,如果有数据直接获取,如果没有数据就报错

        q.put_nowait()#不阻塞,如果可以继续往队列中放数据,就直接放,不能放就报错

      (2)from multiprocessing import JoinableQueue  #可连接的队列

        JoinableQueue是继承Queue,所以可以使用Queue中的方法

        并且JoinableQueue又多了两个方法

        q.join()  用于生产者,等待 q.task_done的返回结果,通过返回结果,生产者就能获得消费者消费了多少个数据

        q.task_done  用于消费者,是指每消费队列中一个数据,就给join返回一个标识.

   2.管道(了解)

     from multipressing import Pipe

     con1,con2 = Pipe()

     管道是不安全的.

     管道是用于多进程之间通信的一种方式.

     如果在单进程中使用管道:  那么就是con1收数据,就是con2发数据.

                    如果是con1发数据,就是con2收数据

     如果在多进程中使用管道,那么就必须是  父进程使用con1收,子进程就必须使用con2发

                       父进程使用con1发,子进程就必须使用con2收

                       父进程使用con2收,子进程就必须使用con1发

                       父进程使用con2发,子进程就必须使用con1收

     在管道中有一个著名的错误叫做EOFError.是指,父进程中如果关闭了发送端,子进程还继续接收数据,那么就会引发EOFError.

 

   3.进程之间的共享内存

     from multiprocessing import Manager,Value

     m = Manager()

     num = m.dict({键:值})

     num = m.list([1,2,3])

   4.进程池

    进程池:一个池子,里面有固定数量的进程.这些进程一直处于待命状态,一旦有任务来,马上就有进程去处理

    因为在实际业务中,任务量是有多有少的,如果任务量特别的多,不可能要开对应那么多的进程数

    开启那么多进程首先就需要消耗大量的时间让操作系统来为你管理它,其次还需要消耗大量时间让cpu帮你调度它.

    进程池还会帮程序员去管理进程池中的进程

    from multiprocessing import Pool

    p = Pool(os.cpu_count() + 1)

    进程最好开p个   p就是cpu核数加上1

    

    进程池有三个方法:

      map(func,iterable)

      func: 进程池中的进程执行的任务函数

      iterable: 可迭代对象,是吧可迭代对象中的每一个元素一次传给任务函数当参数

 

    apply(func,args=()):  同步的效率,也就是说池中的进程一个一个的去执行任务

      func:进程池中的进程执行的任务函数

      args:可迭代对象型的参数,是传给任务函数的参数

      同步处理任务时,不需要close和join

      同步处理任务时,进程池中的所有进程都是普通进程(主进程需要等待其执行结束)

    apply_async(func,args=(),callback=None):  异步的效率,也就是说池中的进程都一次性都去执行任务

    func:进程池中的进程执行的任务函数

    args:可迭代带对象型的参数,是传给任务函数的参数

    callback:回调函数,就是说每当进程池中有进程处理完任务了,返回的结果可以交给函数,由回调函数进行进一步的处理,回调函数只有异步才有,同步是没有的

    异步处理任务时,进程池中的所有进程都是守护进程(主进程代码执行完毕守护进程就结束)

    异步处理任务时,必须加上close和join

 

以上是关于生产者消费者模型,管道,进程之间共享内存,进程池的主要内容,如果未能解决你的问题,请参考以下文章

5 并发编程--队列&生产者消费者模型

joinablequeue模块 生产者消费者模型 Manager模块 进程池 管道

进程间通讯

0515线程

day8

队列生产者消费者模型