Python多处理不确定性(管理器)?

2024-03-29 00:05:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过Manager接口共享dict,结果似乎不同!有时是{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

Tags: 代码infromimportdivforifdef
1条回答
网友
1楼 · 发布于 2024-03-29 00:05:56

您的代码中有一个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,那么其中一个增量可能会由于我上面解释的原因而丢失。在

使用共享字典的另一种方法是让每个进程维护自己的计数集,并在最后聚合这些计数集。这样就很难引入细微的bug。它还可以带来更好的性能特性,因为对进程间通信的需求将更少。在

相关问题 更多 >