如何正确关闭并解除关联Python multiprocessing模块的共享内存?解决使用Pool时的报错问题
解决multiprocessing共享内存访问错误与资源泄漏问题
你的代码遇到了两个核心问题:共享内存找不到的FileNotFoundError,以及进程退出后的资源泄漏警告。我来一步步分析原因并给出修复方案:
问题根源分析
- 进程启动顺序错误:你先创建了
Pool(12),这时候12个子进程已经被fork出来了,但共享内存是之后才创建的。虽然apply是阻塞调用,但部分子进程可能在共享内存初始化完成前就尝试连接它,导致找不到资源的错误。 - 缺少同步机制:多个进程同时修改共享内存中的值会触发竞态条件,最终的计数结果会远小于预期的20(比如多个进程同时读取到同一个旧值,加1后写回去,相当于只加了一次)。
- 异常导致的资源未清理:当子进程因为找不到共享内存抛出异常时,
existing_shm.close()不会被执行,导致资源跟踪器认为有共享内存对象泄漏。
修复后的完整代码
from multiprocessing import Pool, Lock, shared_memory def counter(lock): try: # 连接到已创建的共享内存 existing_shm = shared_memory.SharedMemory(name='shm_counter') c = existing_shm.buf # 用锁保证同一时间只有一个进程修改值 with lock: old_state = c[0] c[0] = old_state + 1 print(c[0]) existing_shm.close() except Exception as e: print(f"子进程执行出错: {e}") if __name__=='__main__': # 第一步:先创建共享内存并初始化值 shm = shared_memory.SharedMemory(create=True, size=1, name='shm_counter') buffer = shm.buf buffer[0] = 0 # 创建进程同步锁 lock = Lock() # 第二步:再创建进程池,确保子进程启动时共享内存已存在 with Pool(12) as p: # 批量提交20次任务 for _ in range(20): p.apply(counter, args=(lock,)) # 最后清理共享内存:先关闭再解除关联 shm.close() shm.unlink()
关键修改说明
- 调整初始化顺序:先创建共享内存和锁,再启动进程池。这样所有子进程启动时,共享内存已经存在,不会出现找不到的错误。
- 添加同步锁:用
Lock包裹修改共享内存的逻辑,确保同一时间只有一个进程能读写共享内存,彻底解决竞态条件问题,最终计数会准确到20。 - 用
with管理进程池:with Pool()会自动处理close()和join()操作,避免手动调用时遗漏步骤,代码更简洁安全。 - 异常捕获:子进程中添加异常处理,避免单个进程出错导致整个任务崩溃,同时保证即使出错也能执行共享内存的关闭操作。
- 重命名共享内存:把名字改成
shm_counter,避免和系统中可能存在的同名共享内存冲突,提升鲁棒性。
这样修改后,你的代码应该能正常运行,不会再出现找不到共享内存的错误,也不会有资源泄漏的警告。
内容的提问来源于stack exchange,提问作者nya_ko314
相关产品推荐
相关产品推荐

