SharedMemory + numpy.ndarray 是最实用高效的进程间通信方案;需显式指定 size 并严格匹配 dtype/shape,子进程须用 name 重新 attach,创建者负责 unlink 防泄漏。

multiprocessing.shared_memory 是 Python 3.8+ 提供的零拷贝共享内存方案,它不走序列化/反序列化,也不依赖操作系统级 IPC(如 shm_open),而是基于 POSIX 共享内存对象封装,适合在 Linux/macOS 上做高频、大块数据交换。Windows 支持有限(仅限于命名共享内存,且需注意 spawn 启动方式)。
直接说结论:用 SharedMemory + numpy.ndarray 组合是最实用、最可控的高效通信路径;单纯靠 ShareableList 做数值密集型操作反而容易踩坑。
创建共享内存时必须显式指定 size,且不能动态扩容
SharedMemory 创建后大小固定,size 参数是硬约束,不是“建议值”。如果后续写入超出范围,会静默越界(写到相邻内存),或触发 BufferError(取决于底层 mmap 映射保护)。
- 必须提前算好所需字节数:比如存一个
shape=(1000, 1000)的np.float64数组,需1000 * 1000 * 8 == 8_000_000字节 - 不要用
size=0或省略size(除非你只打算 attach 已存在的内存块) - 名称(
name)建议手动指定,避免多进程启动竞争导致FileExistsError:例如用os.getpid()或 UUID 生成唯一名
用 numpy.ndarray 关联 shared_memory.buf 是标准做法
shared_memory.buf 是 memoryview 对象,不能直接索引或赋值标量;必须通过 numpy.ndarray(或 array.array)构造视图才能安全读写。
立即学习“Python免费学习笔记(深入)”;
- dtype 和 shape 必须与实际内存布局严格匹配,否则数据错位(例如把
int32当float64读,结果全乱) - 示例:创建 4 个
int64的共享数组shm = shared_memory.SharedMemory(create=True, size=4*8)arr = np.ndarray((4,), dtype=np.int64, buffer=shm.buf) - 别直接对
shm.buf[0] = 42—— 这会报TypeError: 'memoryview' object does not support item assignment
子进程必须显式 attach 已存在的共享内存,不能复用父进程对象
父进程中创建的 SharedMemory 实例不会自动继承给子进程(尤其是 spawn 方式下)。子进程必须用 name 重新打开。
- 主进程创建后,把
shm.name作为参数传给子进程函数 - 子进程中调用
SharedMemory(name=xxx),而不是传入父进程的shm对象 - 忘记
.close()或.unlink()会导致内存泄漏:每个进程都应调用.close();仅由创建者(或约定好的一方)调用.unlink() - 常见错误:
FileNotFoundError表示子进程尝试 attach 一个已被unlink的内存块,或名称拼错
并发写入必须加锁,shared_memory 本身不提供同步机制
SharedMemory 只负责内存映射,不处理竞态。多个进程同时写同一地址,结果不可预测(非原子写、缓存行冲突等)。
- 用
multiprocessing.Lock或Value/Array中的锁机制保护临界区 - 如果只是生产者写、消费者读(单写多读),可不加锁,但需确保写操作完成后再通知读方(例如用
Event或写标记位) -
ShareableList内部用了锁,但只针对列表元素级操作,且性能开销明显,不适合高频数值计算场景
真正容易被忽略的是:共享内存块在进程退出时不会自动释放,即使所有进程都已终止,只要没调用 .unlink(),这块内存就一直留在系统中(Linux 下可见 /dev/shm/ 下的文件)。长期运行的服务若漏掉 unlink,会缓慢耗尽共享内存资源。


















