You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确关闭并解除关联Python multiprocessing模块的共享内存?解决使用Pool时的报错问题

解决multiprocessing共享内存访问错误与资源泄漏问题

你的代码遇到了两个核心问题:共享内存找不到的FileNotFoundError,以及进程退出后的资源泄漏警告。我来一步步分析原因并给出修复方案:

问题根源分析

  1. 进程启动顺序错误:你先创建了Pool(12),这时候12个子进程已经被fork出来了,但共享内存是之后才创建的。虽然apply是阻塞调用,但部分子进程可能在共享内存初始化完成前就尝试连接它,导致找不到资源的错误。
  2. 缺少同步机制:多个进程同时修改共享内存中的值会触发竞态条件,最终的计数结果会远小于预期的20(比如多个进程同时读取到同一个旧值,加1后写回去,相当于只加了一次)。
  3. 异常导致的资源未清理:当子进程因为找不到共享内存抛出异常时,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 18:52:30