Python中用SharedMemoryManager管理可变数量SharedMemory对象遇异常
在生产者-消费者多进程架构中,我希望根据消费者进程数量,使用SharedMemoryManager管理可变数量的SharedMemory对象,因此在管理器上下文范围内通过循环创建SharedMemory实例。但发现仅最后创建的共享内存可通过名称访问,之前的实例似乎已被销毁。
复现问题的Python 3.10代码:
from multiprocessing.managers import SharedMemoryManager from multiprocessing.shared_memory import SharedMemory consumer_process_count = 3 with SharedMemoryManager() as memory_manager: memory_names = [] for i in range(consumer_process_count): shared_memory = memory_manager.SharedMemory(size=1) memory_names.append(shared_memory.name) print(f"Memory {shared_memory.name} created.") for memory_name in memory_names: try: SharedMemory(name=memory_name) except FileNotFoundError: print(f"Memory {memory_name} not found.") else: print(f"Memory {memory_name} found.")
请问是我的操作存在错误,还是SharedMemoryManager本身不支持管理可变数量的SharedMemory对象?我已有不使用SharedMemoryManager的替代方案,但希望借助上下文管理器自动清理资源的特性优化代码。
问题原因
你的操作存在关键错误:循环中每次将新创建的SharedMemory实例赋值给同一个shared_memory变量,导致前一个实例的引用计数直接归零。SharedMemoryManager管理的共享内存对象,当本地实例的引用计数归零时,会触发管理器对该共享内存的销毁操作,因此除了最后一个实例,前面的共享内存都被提前清理了。
解决方法
保留每个SharedMemory实例的引用,而不是仅保存名称。通过将实例存入列表,维持其引用计数大于0,就能避免管理器提前销毁共享内存,直到上下文管理器退出时统一清理。
修改后的代码:
from multiprocessing.managers import SharedMemoryManager from multiprocessing.shared_memory import SharedMemory consumer_process_count = 3 with SharedMemoryManager() as memory_manager: shared_memories = [] # 保存实例引用,避免被提前回收 memory_names = [] for i in range(consumer_process_count): shared_memory = memory_manager.SharedMemory(size=1) shared_memories.append(shared_memory) memory_names.append(shared_memory.name) print(f"Memory {shared_memory.name} created.") for memory_name in memory_names: try: SharedMemory(name=memory_name) except FileNotFoundError: print(f"Memory {memory_name} not found.") else: print(f"Memory {memory_name} found.")
补充说明
SharedMemoryManager完全支持管理可变数量的SharedMemory对象,核心是要确保在需要使用共享内存的周期内,保留对管理器创建的SharedMemory实例的引用,防止其被提前回收销毁。上下文管理器的自动清理特性依然有效,当with块结束时,所有被管理器持有的共享内存都会被自动清理。
内容的提问来源于stack exchange,提问作者Daniel Konečný

