进程是系统进行资源分配和调度的基本单位,拥有独立的地址空间。与线程相比,进程由于资源独立,运行更为稳定。另一方面,进程却不如线程轻量,创建开销更大。
合理应用多进程编程技巧,对提升程序多核处理能力意义重大。然而,进程使用方法因操作系统而异,操作系统原生多进程编程 API 也是五花八门。 Python 将进程编程 原语 进一步抽象,并提供一套简洁的通用 API ,复杂度已降到最低。
接下来,我们以一个最简单的例子,一览为快。
假设,我们需要启动 3 个进程,并行执行下面这个函数:
|
|
首先,我们从标准库 multiprocessing 包中导入 Process 类:
|
|
顾名思义,Process 类用于创建进程对象。我们通过列表推导创建 3 个进程对象:
|
|
注意到,foo 函数作为 target 参数传给了 Process 类。 当 Process 对象启动时,将自动执行 target 指定的 可调用对象 。 它可以是一个函数,也可以是一个对象的某个方法。
现在,我们看到刚创建的进程处于 initial ,即初始状态:
|
|
初始状态表示进程对象完成了创建,但仍未启动,更别说执行 foo 函数了。
接下来,我们调用进程对象 start 方法,将进程逐个启动:
|
|
我们刚启动进程,并陆续看到了它们执行 foo 函数而输出的 hello ,共 3 个。
注意到,有两个 hello 是在提示符出现后才输出的,这是操作系统未能及时调度的缘故。由于进程执行顺序与操作系统调度策略有关,因此不能对子进程执行顺序做任何假设。
由于 foo 函数非常简短,进程很快就执行完毕,并自动停止:
|
|
进程虽然已经执行完毕并停止了,但它们占用的系统资源却仍未释放。因此,别忘了在进程停止后,调用 join 方法将其占用的系统资源进行释放:
|
|
需要特别注意,如果进程还在运行, join 方法将一直阻塞,直到进程退出后才返回。
【小菜学Python】系列文章首发于公众号【小菜学编程】,敬请关注: