就是一个程序在一个数据集上的一次动态执行过程(本质上来讲,就是运行中的程序(代指运行过程),程序不运行就不是进程)
0×01 概念
概念:就是一个程序在一个数据集上的一次动态执行过程(本质上来讲,就是运行中的程序(代指运行过程),程序不运行就不是进程) 抽象概念
组成:
1、程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成
2、数据集:数据集则是程序在执行过程中所需要使用的资源
3、进程控制块:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
阐释:进程与进程之间都占用的是独立的内存块,它们彼此之间的数据也是独立的
优点:同时利用多个 CPU,能够同时进行多个操作
缺点:耗费资源(需要重新开辟内存空间)
0×02 实例
构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
- group: 线程组,目前还没有实现,库引用中提示必须是 None;
- target: 要执行的方法;
- name: 进程名;
- args/kwargs: 要传入方法的参数。
实例方法:
- is_alive():返回进程是否在运行。
- join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的 timeout(可选参数)。
- start():进程准备就绪,等待 CPU 调度
- run():strat()调用 run 方法,如果实例进程时未制定传入 target,这 star 执行 t 默认 run()方法。
- terminate():不管任务是否完成,立即停止工作进程
属性:
- daemon:和线程的 setDeamon 功能一样
- name:进程名字。
- pid:进程号。
0×03 进程创建
3.1 通过调用模块的方式来创建线程
1 | # 进程模块 |
3.2 通过继承类的方式(推荐)
1 | import multiprocessing |
0×04 进程通信
创建进程模块的下队列(Queue)
1 | # 进程之间的通信 Queue |
管道(Pipe)
1 | # 进程之间的通信 Pipe(类似于socket) |
上述实现了进程间的数据通信,那么进程可以达到数据共享么?Sure。
前一节中, Pipe、Queue 都有一定数据共享的功能,但是他们会堵塞进程, 这里介绍的两种数据共享方式都不会堵塞进程, 而且都是多进程安全的。
A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.
A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array.
由上述英文我们了解到,通过 Manager()可以实现进程上的数据共享,并且支持的类型也由很多,接下来看代码
1 | from multiprocessing import Process, Manager |
1 | from multiprocessing import Process, Manager |
0×05 进程同步
5.1 Lock
锁是为了确保数据一致性,比如读写锁,每个进程给一个变量增加 1 ,但是如果在一个进程读取但还没有写入的时候,另外的进程也同时读取了,并写入该值,则最后写入的值是错误的,这时候就需要锁。
1 | # 为什么引申进程同步 |
Lock 同时也实现了 ContextManager API, 可以结合 with 语句使用, 关于 ContextManager, 请移步 Python 学习实践笔记 装饰器 与 context 查看 “ Python 学习实践笔记 装饰器 与 context 查看
5.2 Semaphore
Semaphore 和 Lock 稍有不同,Semaphore 相当于 N 把锁,获取其中一把就可以执行了。 信号量的总数 N 在构造时传入,s = Semaphore(N)。 和 Lock 一样,如果信号量为 0,则进程堵塞,直到信号大于 0。
5.3 进程池
如果有 50 个任务要去执行,CPU 只有 4 核,那创建 50 个进程完成,其实大可不必,徒增管理开销。如果只想创建 4 个进程,让它们轮流替完成任务,不用自己去管理具体的进程的创建销毁,那 Pool 是非常有用的。
Pool 是进程池,进程池能够管理一定的进程,当有空闲进程时,则利用空闲进程完成任务,直到所有任务完成为止
1 | def func(x): |
从上面的例子来看貌似也看不出什么效果,那么接下来自定义一个进程池
关于进程池的 API 用法(并不是只有俩个哦)
apply (每个任务是排队进行,类似于串行失去意义)
apply_async (任务都是并发进行,并且可以设置回调函数) 进程的并发其实可以称之为并行了,可以利用到多核 CPU
1 | import os,time |