DAY 15. python多进程
15.1 进程与程序
程序是计算机存储中一个可执行二进制文件,是静态的,没有占用计算机资源,进程是程序执行后产生的,是可以调用计算机资源的。
15.2 python进程的创建
python创建与管理进程依赖multiprocessing模块,创建进程的方法与创建线程的方法类似,都是使用模块中的Process类,可以显式的实例化该类并调用start()方法来创建,也可以继承改类实现run()方法,并调用改类实例对象的start()方法来实现。
- Process类中的属性和方法
- name: str :进程名
- daemon: bool : 是否为守护进程
- pid: Optional[int] :进程pid(唯一标识)
- exitcode: Optional[int] : 与进程运行有关,进程正在运行他的值是None,要是进程被某个信号结束,便为那个信号
- authkey: bytes : 一个自动生成的32位字符串,与通信安全有关
- sentinel: int : 哨兵,与定时发送消息有关
- start(): 创建线程,内部调用run()方法实现启动线程
- run():启动线程
- terminate():强制终止线程,不做清理,如果该进程还有子进程,子进程会变成孤儿进程,如果有锁未释放,会导致死锁
- is_alive():判断进程是否活着
- join():阻塞主进程等待该进程结束
在3.7之后又加入了两个方法:
- kill():杀死进程
- close():关闭进程池
15.3 僵尸进程和孤儿进程
僵尸进程
- 产生原因:子进程结束后需要父进程调用wait()或waitpid()来释放子进程站有的资源,如果父进程一直或长时间未调用,这部分资源就会被白白占用,比如pid,pid是进程的唯一标识,但他是有限的,如果子进程结束而他的pid长时间没被释放,就会造成pid的浪费,这就是僵尸进程,僵尸进程是有害的,比如僵尸进程过多就会造成pid不足而无法创建新进程
- 解决办法:杀死父进程,使僵尸进程变成孤儿进程,有init进程收养,或者使用signal(SIGCHLD, SIG_IGN)处理僵尸进程,父进程在接收到子进程退出的信号后,直接将其忽略掉,类似于父进程先退出。
孤儿进程
- 产生原因:如果父进程比子进程先死,那子进程的资源也无法释放而成为孤儿进程
- 解决办法:孤儿进程会由init进程收养,init进程是操作系统内核启动后产生的第一个进程,pid=1,由0号进程idle创建,所以孤儿进程是无害的。
15.4 进程并行Pool
Pool类可以提供指定数量的进程供用户调用,当有新的请求提交到Pool中时,如果池还没有满,就会创建一个新的进程来执行请求。如果池满,请求就会告知先等待,直到池中有进程结束,才会创建新的进程来执行这些请求。
属性:
- processes:要创建的最大进程数,省略默认为GPU核数
- initializer:每个进程启动时都默认执行的可调用对象
- initargs:传入给initializer的参数
- maxtasksperchild:允许创建的最大子进程数
方法:
- apply():阻塞式添加一个进程给进程池,类似于可迭代对象的apply()方法,阻塞式会阻塞进程池,直到正在执行的进程结束,造成程序串行,不推荐使用
- apply_async():向进程池中非阻塞的加入一个进程,进程会按系统调度执行
- map():与python中的map类似,将函数作用于列表的每一项(阻塞式)
- map_async():非阻塞式map()
- starmap和starmap_async: 像
map()
方法一样,但iterable
的元素应该是也可以迭代,并将作为参数解压缩。于是func
和(a,b)变为func(a,b)。 - close():关闭进程池,阻止进程加入
- teminate():直接结束未完成的进程,不再处理进程
- join(): 阻塞主进程,必须关闭进程池(在close 或terminate之后运行)
15.5 守护进程
一个进程被设置为守护进程时,会随着主进程结束而立即结束,守护进程不能再创建子进程
15.5 进程同步Lock
进程同步中Lock,RLock, Condition的用法与threading中的用法一样,但使用进程锁会使并发变为串行,牺牲程序效率,推荐使用队列。
15.6 进程间通信
创建进程时,资源会复制一份,所以进程间通信不能像线程那样共享全局变量
Queue(队列):
- 一种先进后出的数据结构
- 方法:
- put():入队
- get():出队
- empty():判断队列为空
- full():判断队列满
- close():关闭队列
Pipe(管道):参考 GitHub
15.7 总结
- 线程和进程:
- 进程是线程的容器
- 线程是资源调度的最小单元
- 进程是资源分配的最小单元
- 程序和进程:
- 程序是一个二进制文件,是静态的,不占用计算机资源
- 进程是程序执行的产物,是一堆资源的总称