我想我已经在这里发现了一个类似的问题,但没有找到一个我能够轻易理解的好解释。我也尝试阅读python doc,但也没有找到详细的解释。
现在这里是代码:
from multiprocessing import Process, Manager
def f(d):
d[1] = [[1]]
if 2 in d.keys():
d[2].append([2])
else:
d[2] = [[2]]
d[3] = [[3]]
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
p1 = Process(target=f, args=(d,))
p2 = Process(target=f, args=(d,))
p1.start()
p2.start
p1.join()
p2.join
print(d)
我有两个进程正在运行并从Manager进程共享一个dict对象。我可以向dict对象添加新的键值对,但如果键已存在则无法修改值。
为什么会这样?如果我们想要修改使用这样的共享对象会出现什么问题?
答案 0 :(得分:2)
首先,你没有开始第二个过程。
p2.start # <--- no `()`
p2.join # <--- no `()`
其次,根据multiprocessing.managers.SyncManager
documentation NOTE:
注意:修改dict和列表代理中的可变值或项目 不能通过管理器传播,因为代理无法通过 知道何时修改其值或项目。 要修改此类项目, 您可以将修改后的对象重新分配给容器代理。
所以,你的程序应该是这样的:
from multiprocessing import Process, Manager
def f(d):
d[1] = [[1]]
if 2 in d: # NOTE: You don't need to use `keys()`. `dict` support `in` operator.
d[2] = d[2] + [[2]]
else:
d[2] = [[2]]
d[3] = [[3]]
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
p1 = Process(target=f, args=(d,))
p2 = Process(target=f, args=(d,))
p1.start()
p2.start()
p1.join()
p2.join()
print(d)
但是,还有另一个问题。以下语句涉及多次读取,写入共享对象;这不是原子的;因此,无法保证上述程序每次都能产生相同的结果。
if 2 in d:
d[2] = d[2] + [[2]]
else:
d[2] = [[2]]
您需要使用锁来确保共享对象只能由一个进程访问。