我写了下面的代码来说明我看到的问题。我正在尝试使用Process.Manager.list()
来跟踪列表并增加该列表的随机索引。
每次生成100个进程,并且每个进程将列表的随机索引递增1.因此,可以预期结果列表的SUM每次都相同,对吗?我得到203到205之间的东西。
from multiprocessing import Process, Manager
import random
class MyProc(Process):
def __init__(self, A):
Process.__init__(self)
self.A = A
def run(self):
i = random.randint(0, len(self.A)-1)
self.A[i] = self.A[i] + 1
if __name__ == '__main__':
procs = []
M = Manager()
a = M.list(range(15))
print('A: {0}'.format(a))
print('sum(A) = {0}'.format(sum(a)))
for i in range(100):
procs.append(MyProc(a))
map(lambda x: x.start(), procs)
map(lambda x: x.join(), procs)
print('A: {0}'.format(a))
print('sum(A) = {0}'.format(sum(a)))
答案 0 :(得分:3)
正如 millimoose 所指出的,这里的问题是self.A[i] = self.A[i] + 1
中发生的竞争条件。在计算self.A[i] + 1
时,self.A[i]
可能已被其他流程更改。
问题的一个可能解决方案是你的问题是将索引传递回父级,然后父级执行添加。
from multiprocessing import Process, Manager
import random
class MyProc(Process):
def __init__(self, B, length):
Process.__init__(self)
self.B = B
self.length = length
def run(self):
i = random.randint(0, self.length-1)
self.B.append(i)
if __name__ == '__main__':
procs = []
M = Manager()
a = range(15)
b = M.list()
print('A: {0}'.format(a))
print('sum(A) = {0}'.format(sum(a)))
for i in range(100):
procs.append(MyProc(b, len(a)))
map(lambda x: x.start(), procs)
map(lambda x: x.join(), procs)
for i in b:
a[i] = a[i] + 1
print('A: {0}'.format(a))
print('sum(A) = {0}'.format(sum(a)))
将一个元素附加到数组只是一个操作,因此避免了竞争条件。
答案 1 :(得分:1)
通过上面的评论得出答案,因为以下行发生了竞争条件:
self.A[i] = self.A[i] + 1
实际上是两个操作,__getitem__
和__setitem__