我希望以下代码能够打印[{0: 100}]
,
因为它在updateList
中做了一百倍的加号
反过来,它会打印[{0: 0}]
问题是什么以及如何纠正它?
from multiprocessing import Process, Lock, Value,Manager
class myWorker:
def __init__(self, lock, driver, i):
self.idx=i
self.driver=driver
self.lock=lock
def run(self):
self.driver.updateList(self.lock,self.idx)
class driver(object):
def __init__(self):
manager=Manager()
self.lock=Lock()
self.lst=manager.list()
self.dict1=manager.dict({0:0})
self.lst.append(self.dict1)
def workerrun(self,lock, i):
worker1=myWorker(lock,self,i)
worker1.run()
def run(self):
D=[Process(target=self.workerrun,args=(self.lock,i)) for i in range(10)]
for d in D:
d.start()
for d in D:
d.join()
def updateList(self,l,i):
with self.lock: # acquire lock
for j in range(10):
self.lst[0][0]+=1
print ("update from", i)
if __name__=='__main__':
dr=driver()
dr.run()
print(dr.lst)
答案 0 :(得分:7)
def updateList(self,l,i):
with self.lock: # acquire lock
for j in range(10):
d = self.lst[0]
d[0] += 1
self.lst[0]=d
print ("update from", i,self.lst[0])
来自docs 的
注意对dict和列表代理中的可变值或项目的修改不会通过管理器传播,因为代理无法知道其值或项目何时被修改。要修改此类项目,可以将修改后的对象重新分配给容器代理:
看到您已经拥有dict1
,您可以直接更新:
def updateList(self,l,i):
with self.lock: # acquire lock
for j in range(10):
self.dict1[0]+=1
print ("update from", i,self.lst[0])
答案 1 :(得分:0)
您可以直接更新字典来纠正它。
def updateList(self,l,i):
with self.lock: # acquire lock
for j in range(10):
self.dict1[0] += 1
print ("update from", i)
虽然,为什么循环添加10?摆脱循环,只需self.dict1[0] += 10
。
答案 2 :(得分:0)
multiprocessing.Manager()
如果您看到创建列表和字典的时间,则会返回multiprocessing.managers.SyncManager
,您实际上已获得其代理。这意味着,您在列表中附加的内容不是您在管理器中创建的{0:0}
而是代理(副本)。
self.dict1=manager.dict({0:0})
#this:
self.lst.append(self.dict1)
#is the same as doing this:
self.lst.append({0:0})
所以,在updatelist方法中:
def updateList(self,l,i):
with self.lock: # acquire lock
for j in range(10):
self.lst[0][0]+=1
# is the same as doing:
# example: self.lst == [{0:x}]
proxy = self.lst
# you get a copy of actual list
# proxy == [{0:x}]
dict = proxy[0]
dict[0]+=1
# proxy == [{0:x+1}]
# BUT
# self.lst == [{0:x}]
这意味着您正在制作副本,更改它们,然后不使用它们。您需要更改以使用新值分配列表,以便更改所有进程:
def updateList(self,l,i):
with self.lock: # acquire lock
dict0 = self.lst[0]
for j in range(10):
dict0[0]+=1
self.lst[0] = dict0