CPU密集型任务转多进程如何实现全局变量共享且尽量少改代码?
解决方案
不需要大改现有代码,只需要把原有的普通容器替换为multiprocessing模块提供的进程安全容器即可,核心修改只有3处:
- 把原来的普通任务队列替换为
multiprocessing.Queue,本身是进程安全的,主进程塞任务、子进程取任务都不需要手动加锁 - 需要在子进程修改的少量变量,用
multiprocessing.Manager创建的可共享对象即可,比如Manager.list()、Manager.dict(),用法和原生的list、dict完全一致,不需要改动原有的操作逻辑 - 把队列和共享变量作为参数传给子进程入口函数即可,原有业务计算逻辑几乎不需要调整
修改后的可运行代码如下:
import multiprocessing # 替换为进程安全的共享容器,用法和原生list完全一致 manager = multiprocessing.Manager() target = manager.list() # 替换为进程安全队列,自带锁无需手动处理并发 queue = multiprocessing.Queue() def func(a,b,target): temp=list() for i in range(0,a): # 补全原代码遗漏的冒号 for j in range(0,b): temp.append('a'+str(i)+'b'+str(j)) # 直接修改共享list对象内容,不要重新赋值变量名 target[:] = temp def process_func(queue, target): go=True while go: # 从队列取任务,队列空时会自动阻塞等待 task = queue.get() # 任务为None时退出循环,可根据需求自定义退出逻辑 if task is None: go = False break func(task[0], task[1], target) if __name__=='__main__': # 把队列和共享变量传给子进程 p = multiprocessing.Process(target=process_func, args=(queue, target)) p.start() # 测试:主进程添加任务 queue.put((3, 2)) # 添加结束标记 queue.put(None) p.join() # 打印子进程修改后的结果 print(target)
额外说明
- 如果需要启动多个子进程并行计算,直接创建多个Process实例,传入同一个queue和共享变量即可,不需要调整其他代码
- 如果不需要实时共享变量,仅需要获取子进程的最终计算结果,也可以不用Manager,直接让func返回结果,子进程把结果put到另一个结果队列,主进程从结果队列取数即可,性能更高
内容的提问来源于stack exchange,提问作者PythonNoob
相关产品推荐
相关产品推荐

