并发编程之多进程
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,'kuck',) 4 kwargs表示调用对象的字典,kwargs={'name':'kuck','age':18} 5 name为子进程的名称
-
-
方法
-
1 group参数未使用,值始终为None 2 target表示调用对象,即子进程要执行的任务 3 args表示调用对象的位置参数元组,args=(1,2,'kuck',) 4 kwargs表示调用对象的字典,kwargs={'name':'kuck','age':32} 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()
-