多处理模块
from __future__ import print_function
import multiprocessing
def countdown(count):
while count > 0:
print("Count value", count)
count -= 1
return
if __name__ == "__main__":
p1 = multiprocessing.Process(target=countdown, args=(10,))
p1.start()
p2 = multiprocessing.Process(target=countdown, args=(20,))
p2.start()
p1.join()
p2.join()
这里,每个函数都在一个新进程中执行。由于 Python VM 的新实例正在运行代码,因此没有 GIL
,你可以在多个内核上运行并行操作。
Process.start
方法启动这个新进程,并使用参数 args
运行 target
参数中传递的函数。Process.join
方法等待进程 p1
和 p2
的执行结束。
根据 python 的版本和运行代码的平台形式,新进程的启动方式不同,例如 :
- Windows 使用
spawn
来创建新进程。 - 对于 unix 系统和早于 3.3 的版本,使用
fork
创建流程。
请注意,此方法不考虑 fork 的 POSIX 使用,因此会导致意外行为,尤其是在与其他多处理库交互时。 - 使用 unix 系统和 3.4+版本,你可以选择在程序开始时使用
multiprocessing.set_start_method
启动fork
,forkserver
或spawn
的新流程。forkserver
和spawn
方法比分叉慢,但避免一些意想不到的行为。
POSIX fork 用法 :
在多线程程序中的 fork 之后,子进程可以安全地只调用异步信号安全函数,直到它调用 execve 为止。
( 见 )
使用 fork,将为所有当前互斥锁启动一个具有完全相同状态的新进程,但只会启动 MainThread
。这是不安全的,因为它可能导致竞争条件,例如 :
- 如果你在
MainThread
中使用Lock
并将其传递给另一个线程,该线程可能会在某个时刻将其锁定。如果fork
同时发生,则新进程将以锁定锁启动,该锁将永远不会释放,因为此新进程中不存在第二个线程。
实际上,这种行为不应该在纯 python 中发生,因为 multiprocessing
正确处理它,但如果你正在与其他库交互,这种行为可能会发生,导致你的系统崩溃(例如在 macOS 上有 numpy /加速)。