假设我使用multiprocessing.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)
则如果我们等待足够长的时间,我们知道父进程将看到CCD_ 9和CCD_。问题是,我们可以看到介于两者之间的可能状态是什么。如果管理器中存在某种全局同步,我们将只能看到a,b
的以下值对:[],[]
、[1],[]
或最终状态[1],[2]
。但是,如果没有这样的同步,我们可能能够看到[],[2]
(例如,如果关于附加到b
的消息更快地到达父级,或者队列的轮询顺序不是我们期望的(我们期望什么?((。我希望不必查看源代码(在未来的版本中也可能会更改(,而是得到一个通用的保证(如果有的话(。希望这能澄清问题。
在您显示的示例中,您正在处理一个托管的列表。此列表存在于执行manager = multiprocessing.Manager()
时创建的进程中。变量a
和b
实际上是代理对象。当在这些代理上调用方法时,从一个进程的地址空间到SynchManager的地址空间(multiprocessing.SyncManager
是通过调用multiprocessing.Manager()
创建的类(执行远程方法调用(Linux下的通信机制是套接字,Windows下的命名管道(,并且实际方法由在SyncManager的地址空间中运行的线程执行,该线程侦听套接字连接在连接上回复(返回给调用者(,直到方法调用完成。
更新
根据OP的更新问题,a
和b
列表的可能状态按时间顺序排列:
a
->[],b
->[]- CCD_ 26->[1] ,
b
->[] - CCD_ 28->[1] ,
b
->[2]
没有其他可能的状态,因为对a.append(1)
的调用将被阻止,直到a
列表添加了值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)