首页 > 解决方案 > 在python中同步两个共享对象的读/写操作

问题描述

假设我使用 amultiprocessing.Manager创建两个共享对象并将它们传递给子进程,该子进程开始写入这些对象:

manager = multiprocessing.Manager()
a = manager.list()
b = manager.list()
subprocess = MyProcess(a,b)
subprocess.start()  # writing to a and b starts here

# inspect a and b - in what order will changes appear?

有没有办法确保这些写入在父进程中反映的顺序与在子进程中执行写入的顺序相同?如果我register()的类有两个成员,并且子流程对这两个成员进行了更改怎么办?

有没有更一般地回答这些“操作顺序”问题的参考资料?(我在文档中找不到这个)。例如:如果我们生成第二个子进程subprocess_2,它也会在和上进行一些写入和读取a-b我们能说什么关于订单更改将反映在父进程和中subprocess_2

简单、详细的示例:按照 Booboo 的示例,如果 MyProcess (的子类multiprocessing.Process)实现run()如下:

def run(self) :
    a.append(1)
    b.append(2)

那么如果我们等待足够长的时间,我们就知道父进程会看到a == [1]and b == [2]。问题是我们可以在两者之间看到哪些可能的状态。如果管理器中有某种​​全局同步,我们将只能看到以下对a,b:[],[][1],[]最终状态的值[1],[2]。但是如果没有这样的同步,我们也许可以一瞥[],[2](例如,如果关于追加到b父节点的消息更快,或者队列的轮询顺序不是我们所期望的(我们期望什么?)) . 我希望不必查看源代码(在未来的版本中也可能会更改),而是希望得到一个一般性的保证,如果有的话。希望这能澄清这个问题。

标签: pythonconcurrencymultiprocessingsubprocess

解决方案


在您展示的示例中,您正在处理一个托管列表。此列表存在于您执行时创建的进程中manager = multiprocessing.Manager()。变量ab实际上是代理对象。当在这些代理上调用方法时,将执行从一个进程的地址空间到 SynchManager 的地址空间(multiprocessing.SyncManager即由调用创建的类)的远程方法调用(通信机制是 Linux 下的套接字和 Windows 下的命名管道) to multiprocessing.Manager()) 并且实际方法由运行在 SyncManager 的地址空间中的线程执行,该线程侦听套接字连接,并且在方法调用完成之前不会回复连接(返回给调用者)。

更新

根据 OP 的更新问题,ab列表的可能状态按时间顺序排列:

  1. a-> [],b-> []
  2. a-> [1],b-> []
  3. a-> [1],b-> [2]

没有其他可能的状态,因为调用a.append(1)将阻塞,直到a列表附加了 value 1。想象一下下面的代码:

a.append(1)
# How can the following assertion fail?
# Who would implement a list in such a way where this could fail?
assert(1 in a)
b.append(b)

推荐阅读