如何使用multiprocessing.Pool().map修改共享对象A?
解决Python多进程中无法修改共享对象的问题
这个问题我之前帮不少开发者捋清楚过——本质是多进程的内存隔离特性在搞鬼!当你用multiprocessing.Pool创建子进程时,每个子进程都会复制一份父进程的内存空间,你在子进程里修改的A只是它自己副本里的那个,根本不会同步回父进程的原始A,这就是为什么并行执行后父进程的A还是初始值。
下面给你两种实用的解决方案,分别适配不同的场景:
方法一:用multiprocessing.Array(适合固定大小的基础类型数组)
Array是多进程安全的共享内存对象,能直接在父子进程间共享数据,适合像你这种固定长度的整数列表场景。
修改后的代码如下:
import multiprocessing def square(i, shared_A): shared_A[i] = 2 + shared_A[i] return i * i if __name__ == "__main__": # 创建共享数组,指定类型为整数('i'),初始值[1,2] A = multiprocessing.Array('i', [1, 2]) # 串行执行测试 square(0, A) square(1, A) print(list(A)) # 输出 [3, 4] # 重置共享数组 A[:] = [1, 2] # 并行执行 with multiprocessing.Pool() as pool: # 用starmap传递多个参数给square函数 pool.starmap(square, [(0, A), (1, A)]) print(list(A)) # 输出 [3, 4]
方法二:用multiprocessing.Manager(适合灵活的列表/字典等复杂结构)
如果你的共享对象需要更灵活的操作(比如动态增删元素),那Manager就更合适了——它会启动一个专门的管理进程来维护共享对象,子进程通过代理访问,支持各种Python标准数据结构。
代码示例:
import multiprocessing def square(i, shared_A): shared_A[i] = 2 + shared_A[i] return i * i if __name__ == "__main__": with multiprocessing.Manager() as manager: # 创建共享列表 A = manager.list([1, 2]) # 串行测试 square(0, A) square(1, A) print(list(A)) # 输出 [3, 4] # 重置共享列表 A[:] = [1, 2] # 并行执行 with multiprocessing.Pool() as pool: pool.starmap(square, [(0, A), (1, A)]) print(list(A)) # 输出 [3, 4]
几个关键注意点:
- 别再用全局变量传共享对象了!必须把共享对象作为参数显式传递给子进程函数,不然子进程只会操作自己的副本。
Array的性能比Manager好一些,因为它直接用共享内存,而Manager需要进程间通信同步数据,性能敏感的场景优先选Array。- Windows系统下一定要把多进程代码放在
if __name__ == "__main__":块里,不然会触发重复创建进程的bug,踩过坑的人都懂😅
内容的提问来源于stack exchange,提问作者J. Lin
相关产品推荐
相关产品推荐

