在 Python 中,在处理线程时,内存中的对象可以无复制地同时被所有线程访问。然而,在通过 multiprocessing 处理进程时,标准的 Python 对象(例如列表、字典)通过序列化(通常使用 pickle)在进程之间传递,每个进程获取对象的副本。在一个进程中更改对象不会反映在另一个进程的副本中。
multiprocessing.Manager().dict()。# 多进程 from multiprocessing import Process, Manager def worker(d): d['a'] = 42 if __name__ == '__main__': # 普通的 dict 在进程之间不起作用 managed_dict = Manager().dict() p = Process(target=worker, args=(managed_dict,)) p.start(); p.join() print(managed_dict['a']) # 42
在什么情况下,编辑一个进程中的普通列表(list)会反映到另一个进程?
永远不会,如果你在使用 multiprocessing。普通的 Python 对象不会在进程之间共享。要实现共享,必须使用特殊的原语——管理器对象(例如,Manager().list(),Manager().dict()),它们在进程之间同步状态。
故事
一个网络爬虫开发团队将任务队列初始化为列表,并通过 multiprocessing 将其分配给进程。任务“丢失”是因为进程无法看到彼此的更新。他们改为使用 Manager().list()。
故事
在一个分析服务中,试图在线程中收集嵌套的 dict 日志。在高负荷场景下,这导致了竞争条件和数据损坏,因为缺乏锁。
故事
在 ETL 服务中,在处理阶段尝试收集的数据对象在多个进程中发现重复/丢失数据:程序员没有考虑到每个进程都在处理自己的结构副本,而不是共享的结构。