请检查以下代码
from multiprocessing import Process
return_dict = dict({})
print "address in parent %s " % id(return_dict)
def f(return_dict):
print "address in child %s " % id(return_dict)
p = Process(target=f, args=(return_dict, ))
p.start()
p.join()
输出
address in parent 23059696
address in child 23059696
我在父进程和子进程中打印dict的地址。他们是一样的。但是如果我在子进程中更改了dict,则更改不会影响父进程中的dict。
所以我假设dict是内存中的两个不同对象。但为什么那里的地址是一样的呢?
有些人可能会说它是正在处理的相对地址,但为什么相对地址需要相同?
答案 0 :(得分:1)
在您的平台上,multiprocessing
使用分叉来生成子进程。以这种方式分叉进程可以让子进程在写时复制方案中使用完全相同的内存区域。
因此,当子进程启动并且字典被传递到f()
函数时,它仍然是相同的字典对象。它已从父进程“继承”。
接下来,对象的id()
值是虚拟内存地址。内存由您的操作系统虚拟化;每个进程都给出了物理内存区域,但是它们在该空间中的地址由OS翻译。在分叉时,子进程被赋予相同的虚拟地址空间,并且copy-on-write 透明地在需要时生成副本,其中相同的虚拟内存地址范围现在映射到不同的物理内存块上。因此,从Python子进程的角度来看,id()
不会改变,但它不再引用同一块物理内存。 {em} os.getpid()
和id()
的组合是唯一的,但id()
的值不是唯一的,而不是跨进程。
如果您在Windows上运行相同的代码(不支持分叉),您将看到ID始终不同。 Windows子进程无法继承对象。
此外,您通常希望避免在multiprocessing
代码中使用全局共享可变对象;突变只在单个子进程中可见,但进程可以重用,从而产生不一致的结果。