并发编程之多进程(更新中...)

并发编程之多进程

multiprocessing模块介绍

  • 功能
    • 子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

Process类使用

Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)  
强调:
    1. 需要使用关键字的方式来指定参数 
    2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号
  • 参数

    • 1 group参数未使用,值始终为None
      2 target表示调用对象,即子进程要执行的任务
      3 args表示调用对象的位置参数元组,args=(1,2,'egon',)
      4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
      5 name为子进程的名称
  • 方法

    • 1 group参数未使用,值始终为None 
      2 target表示调用对象,即子进程要执行的任务
      3 args表示调用对象的位置参数元组,args=(1,2,'egon',)
      4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
      5 name为子进程的名称
  • 属性

    • 1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置 
      2 p.name:进程的名称
      3 p.pid:进程的pid
      4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
      5 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功
  • .join方法的使用

    • #作用:父进程等待子进程结束
      from multiprocessing import Process
      def task(i):
          print(i)
      if __name__ == '__main__':
          for i in range(10):
              p = Process(target=task,args=(i,))
              p.start()
              p.join()
          print("主进程结束")

多路复用技术

  • 空间隔离
    • 多个程序共用一个内存条,彼此隔离,物理级别隔离
  • 时间隔离
    • 多个程序共用一个cpu
  • cpu并行情况下切换的条件
    • i/o阻塞
    • 占用时间过长

串行、并行、并发

  • 串行:完完整整的执行完一个程序再执行下一个程序
  • 并发:单核cpu同时运行多个程序
  • 并行:多个cpu同时运行多个程序

开启子进程的两种方式

  • 方式1

    • from multiprocessing import Process
      def task():
          pass
      if __name__ == '__main__':
          p = Process(target=task)
          p.start()
  • 方式2

    • from multiprocessing import Process
      class myP(Process):
          def run(self):
              pass
      if __name__ == '__main__':
          p = myP()
          p.start()

僵尸进程、孤儿进程、守护进程

  • 僵尸进程

    • 没有死透的子进程(pid并没有被父进程回收)
  • 孤儿进程

    • 父进程结束,子进程还在运行,孤儿进程通常会被init接管,init相当于孤儿院,会等待子进程运行结束后回收
  • 守护进程

    • 在主进程最后一行代码结束之后立即结束

    • p = Process(target=task)
      p.daemon = True

进程锁的概念与用途

  • 把锁住的代码变成串行

  • 与join比较,join将所有的子程序变成串行,而进程锁只是将锁住的代码变成串行

  • 实例代码

    • from multiprocessing import Process,Lock
      import time
      def task():
          print("11")
      def task1():
          print("2222")
      def task3(lock1):
          task()
          lock1.acquire()
          time.sleep(2)
          task1()
          lock1.release()
      if __name__ == '__main__':
          lock1 = Lock()
          for i in range(30):
              p = Process(target=task3,args=(lock1,))
              p.start()

队列(队列(Queue) = 管道(PIPE) + 锁(Lock))

  • 队列赋值

  • q = Queue(队列中的数的最大数量)
    q.put(block=True,timeout=5) 参数block的意义在队列达到最大数量时是否阻塞,默认为阻塞(True)
    timeout的意义是设置最大阻塞时间
  • 队列取值

    • q.get(block=True,timeout=5) 这里的block与timeout与上面的一样
  • 生产者消费者模型

    • 生产者<---->队列<----->消费者

    • 作用:生产消费者模型大大提高了生产者的生产效率和消费者的消费效率.

    • Joinablequeues使用

      • q.put(相当于在队列中+1) 
        q.get();q.task_dowm()相当于在队列中减一
      • 这里面的join的作用是等待计数器为0
  • 代码实现

    • from multiprocessing import JoinableQueue,Process
      import time
      def shengchanzhe(q,name,food):
          for i in range(1,3):
              print(f"{name}生产了{food}{i}")
              res = f"{food}{i}"
              q.put(res)
      
      def xiaofeizhe(q,name):
          while True:
              res = q.get()
              time.sleep(1)
              print(f"{name}吃了{res}")
              q.task_done()
      if __name__ == '__main__':
          q = JoinableQueue()
          p1 = Process(target=shengchanzhe,args=(q,'厨师1','包子'))
          p2 = Process(target=shengchanzhe,args=(q,'厨师2','面条'))
          p3 = Process(target=shengchanzhe,args=(q,'厨师3','米饭'))
          c1 = Process(target=xiaofeizhe,args=(q,'小明'))
          c2 = Process(target=xiaofeizhe,args=(q,'小红'))
          p1.start()
          p2.start()
          p3.start()
          c1.daemon=True
          c2.daemon=True
          c1.start()
          c2.start()
          p1.join()
          p2.join()
          p3.join()
          q.join()

猜你喜欢

转载自www.cnblogs.com/kuck/p/11530355.html