简体   繁体   中英

python multiprocessing.Process.Manager not producing consistent results?

I've written the following code to illustrate the problem I'm seeing. I'm trying to use a Process.Manager.list() to keep track of a list and increment random indices of that list.

Each time there are 100 processes spawned, and each process increments a random index of the list by 1. Therefore, one would expect the SUM of the resulting list to be the same each time, correct? I get something between 203 and 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)))

As millimoose points out, the problem here is a race condition occurring in self.A[i] = self.A[i] + 1 . By the time self.A[i] + 1 has been calculated, self.A[i] could have already been changed by another process.

A possible solution to your problem is to your problem is to pass the index back to the parent, which then performs the addition.

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)))

Appending an element to an array is only one operation, thus the race condition is avoided.

Answer came up through the comments above, there is a race condition happening because the following line:

self.A[i] = self.A[i] + 1

is in fact two operations, a __getitem__ and a __setitem__

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM