Python 3.x 中如何使用multiprocessing模块进行进程间通信

1. Multiprocessing模块简介

Python 3.x中的模块提供了一种便捷的方式来利用多核/多CPU的计算能力,从而提高程序的运行效率。该模块中提供了各种进程间通信的方式,如队列、管道等,以及进程池、锁等工具。

1.1 进程与线程的区别

在并行编程中,针对可并行的任务,我们一般是通过进程或者线程的方式来实现多任务的并行执行。进程与线程的主要区别如下:

进程拥有独立的内存空间,每个进程之间相互独立,互不影响;而线程共享其所在进程的内存空间

每个进程由自己的程序代码、数据集、堆栈和其他系统资源组成;线程通常被定义为进程中的轻量级实体,它们共享进程的上下文,并可使用该上下文中的共享数据及共享句柄等

在进程间通信时,需要使用操作系统提供的IPC(Interprocess Communication)机制,如管道、队列、共享内存等;在同一个进程内的线程间通信,可直接共享变量和对象,或者使用Python提供的线程同步机制,如锁、信号量等

进程的创建、销毁、切换等操作,需要操作系统提供帮助,代价较大;线程的创建、销毁、切换等操作较为轻量级

1.2 Multiprocessing模块的基本介绍

模块提供了类,可用于创建新的进程。具体使用方式如下:

import multiprocessing

def my_function(num):

print(f"Process {num} started")

if __name__ == '__main__':

p1 = multiprocessing.Process(target=my_function, args=(1,))

p2 = multiprocessing.Process(target=my_function, args=(2,))

p1.start()

p2.start()

p1.join()

p2.join()

上述代码创建了两个新的进程,它们分别执行了函数,其中参数表示传递给该函数的参数。需要注意的是,由于模块会自动导入当前文件,因此在多进程代码中需要判断是否处于主进程的代码块中,否则会引起意想不到的问题。

2. 进程间通信

在多进程编程中,常常需要进行进程间通信,以实现数据共享或者协调进程之间的行为。Python中的模块提供了多种进程间通信的方式,如队列、管道、共享内存等。

2.1 队列(Queue)

队列是一种常用的线程同步工具,可用于进程之间的通信。是一个线程安全的队列类,实现了多进程之间的通信。它与类的差别在于,可以跨进程使用。

from multiprocessing import Process, Queue

def worker(q):

while True:

item = q.get()

if item is None:

break

print(item)

if __name__ == "__main__":

q = Queue()

p1 = Process(target=worker, args=(q,))

p2 = Process(target=worker, args=(q,))

p1.start(); p2.start()

for i in range(10):

q.put(i)

q.put(None)

q.put(None)

p1.join(); p2.join()

上述代码中,首先创建了一个对象,并创建了两个进程,它们从队列中读取数据进行处理。主进程将数据放入队列中,并向队列中添加两个,以表示已经将所有数据处理完毕。进程在读取到时,跳出循环退出运行。

2.2 管道(Pipe)

管道是一种常用的进程间通信方式,可实现双向数据传输。管道由队列构成,允许多个进程同时对管道进行读写操作。Python中的模块提供了创建管道的方法。

from multiprocessing import Process, Pipe

def writer(conn, msg):

conn.send(msg)

conn.close()

if __name__ == '__main__':

parent_conn, child_conn = Pipe()

p = Process(target=writer, args=(child_conn, 'Hello, World!'))

p.start()

print(parent_conn.recv())

p.join()

上述代码中,首先创建了一个管道,然后创建了一个进程,该进程向管道中写入数据,最后主进程从管道中读取数据并打印。

2.3 共享内存(Value、Array)

共享内存是一种高效的进程间通信方式,可以不涉及操作系统调用,直接将一段内存区域映射到多个进程的地址空间中,从而完成数据共享。

from multiprocessing import Process, Value, Array

def f(n, a):

n.value = 3.1415926

for i in range(len(a)):

a[i] *= i

if __name__ == '__main__':

num = Value('d', 0.0)

arr = Array('i', range(10))

p = Process(target=f, args=(num, arr))

p.start()

p.join()

print(num.value)

print(arr[:])

上述代码中,首先创建了一个对象和一个对象,然后创建了一个进程,该进程将的值设置为3.1415926,将中的每个元素乘以其下标,最后主进程打印的值。

3. 总结

模块提供了多种进程间通信方式,如队列、管道、共享内存等,可用于协调进程之间的行为或者完成数据共享。我们可以根据具体情况,选择最适合自己的进程间通信方式。需要注意的是,在多进程编程中,由于存在多个进程同时访问共享资源的问题,需要特别注意数据的同步与互斥,以避免出现意想不到的错误。

后端开发标签