我正试图通过Manager
界面分享一个字典,结果似乎有所不同!有时它是{1: 8, 2: 3, 3: 2, 4: 1}
,有时是{1: 6, 2: 3, 3: 2, 4: 1}
,{1: 7, 2: 3, 3: 2, 4: 1}
等。这只是计算除数,应该确定性地工作......
代码在这里:
from multiprocessing import Process, Manager
def div(x,d):
for i in range(1,x):
if x%i == 0:
try:
d[i] +=1
except:
d[i]=1
mgr = Manager()
d = mgr.dict()
w = [Process(target=div,args=(i,d)) for i in range(1,10)]
for k in w:
k.start()
for k in w:
k.join()
print d
答案 0 :(得分:4)
您的代码中有一个race condition,就在这里:
try:
d[i] += 1
except:
d[i] = 1
如果d[i]
尚不存在且两个进程几乎同时到达d[i] += 1
,请考虑会发生什么。两者都将抛出异常,两者都将执行d[i] = 1
。最终结果:d[i]
为1
而不是2
。你已经失去了增量!
经过仔细检查,即使单独d[i] += 1
也可能不是原子的,因此对竞争条件开放。在内部,d[i] += 1
按以下操作顺序执行:
i
的值; i
设置值。这三个操作中的每一个都是原子的和正确的,但似乎没有任何东西可以保证整个序列的原子性。如果两个进程同时尝试对同一个d[i] += 1
执行i
,其中一个增量可能会因为我上面解释的原因而丢失。
使用共享字典的另一种方法是为每个进程维护自己的一组计数,并在最后聚合这些集合。这样就很难引入微妙的错误。它还可以带来更好的性能特性,因为对进程间通信的需求会减少。