Python多处理中写入共享内存(列表)的同步

我有以下代码:


import multiprocessing

manager = multiprocessing.Manager()

如果列表的长度小于 4,则附加列表或创建一个具有初始值 'y' 的新列表的函数。


def f(my_array):

    if len(my_array) < 4:

        my_array.append('x')

    else:

        my_array = ['y']

    print(my_array)

列表的初始化和创建过程。


if __name__ == '__main__':

    my_array = manager.list(['a', 'b', 'c'])


    p1 = Process(target=f, args=(my_array))

    p2 = Process(target=f, args=(my_array))

    p3 = Process(target=f, args=(my_array))

    p4 = Process(target=f, args=(my_array))

    p5 = Process(target=f, args=(my_array))


    p1.start()

    p2.start()

    p3.start()

    p4.start()

    p5.start()


    p1.join()

    p2.join()

    p3.join()

    p4.join()

    p5.join()

我得到的输出:


['a', 'b', 'c', 'x']

['y']

['y']

['y'] 

['y']

我不明白为什么列表只附加一次。我希望在第三个输出行中我会观察到列表 ['y'] 附加了 'x',所以 ['y', 'x'],第四个 ['y', 'x', 'x']等等。似乎共享内存泄漏或不允许多个进程的函数进行更改。我该怎么做才能实现目标行为?


人到中年有点甜
浏览 280回答 1
1回答

慕桂英4014372

同步是您的示例中缺少的一点。manager.list只是一个list单独的服务器进程中的正常情况,您的工作进程可以通过代理对象进行修改。您的进一步流程恰好同时检查len(my_array)。没有同步,这告诉他们应该等到另一个进程完成它的操作,包括执行此长度检查并根据此检查的结果执行操作。您的更新操作不是原子操作,您需要通过在您的操作周围使用 manager.lock 来实现它。您的代码中还有另一个问题,您重新绑定my_array以指向普通 list ['y'],而不是更新/修改 shared manager.list。你是不是修改manager.list与设置过程my_array = ['y']中,manager.list保持它的价值['a', 'b', 'c', 'x']通过第一个工作流程,直到程序结束,从第一个修改。from multiprocessing import Process, Managerdef f(my_array, lock):&nbsp; &nbsp; with lock:&nbsp; &nbsp; &nbsp; &nbsp; if len(my_array) < 4:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my_array.append('x')&nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my_array[:] = []&nbsp; # clear list inplace by assigning&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # empty list to slice of manager.list&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my_array.append('y')&nbsp; &nbsp; print(my_array)if __name__ == '__main__':&nbsp; &nbsp; N_WORKERS = 5&nbsp; &nbsp; with Manager() as manager:&nbsp; &nbsp; &nbsp; &nbsp; my_array = manager.list(['a', 'b', 'c'])&nbsp; &nbsp; &nbsp; &nbsp; lock = manager.Lock()&nbsp; &nbsp; &nbsp; &nbsp; pool = [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Process(target=f, args=(my_array, lock)) for _ in range(N_WORKERS)&nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; &nbsp; &nbsp; for p in pool:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.start()&nbsp; &nbsp; &nbsp; &nbsp; for p in pool:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.join()&nbsp; &nbsp; &nbsp; &nbsp; # Leaving the context-manager block will shut down the manager-process.&nbsp; &nbsp; &nbsp; &nbsp; # We need to convert the manager-list to a normal list in the parent&nbsp; &nbsp; &nbsp; &nbsp; # to keep its values available for further processing in the parent.&nbsp; &nbsp; &nbsp; &nbsp; result = list(my_array)&nbsp; &nbsp; print(f'result: {result}')示例输出:['a', 'b', 'c', 'x']['y']['y', 'x']['y', 'x', 'x']['y', 'x', 'x', 'x']result: ['y', 'x', 'x', 'x']Process finished with exit code 0
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python