import multiprocessing as mp
class Job:
def __init__(self,name):
self.name=name
class A:
def __init__(self,x):
self.x=x
def run(self,job):
self.x+=1
print(id(self.x),self.x,job.name)
def mul_process_test(self):
j1=Job('hello')
j2=Job('world')
p1=mp.Process(target=self.run,args=(j1,))
p2=mp.Process(target=self.run,args=(j2,))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ =='__main__':
a=A(1)
a.mul_process_test()
print(id(a.x),a.x)
以上代码的结果为:
10919360 2 hello
10919360 2 world
10919328 1
似乎两个进程中的self.x
具有相同的ID,10919360(这对我来说没有意义),但与主进程具有不同的ID(对我来说却有意义)。
我在Linux中使用python3.5,如文档所述,默认的start方法采用类似fork的方式来启动新进程。我想知道两个过程中self.x
的ID为什么相同。
mp.Process
开头的进程)之间是否共享任何内容?
答案 0 :(得分:3)
id
s只是内存地址。 CPython(作为实现的详细信息)使用小的int
缓存,因此从-5到256的所有数字都是单例。因此,您的子进程会从父进程复制相同的虚拟地址表,并继承相同的小型int
缓存。当他们计算self.x += 1
时,他们会查找相同的2
缓存值。
现在,从技术上讲,由于使用CPython参考计数,2
的每个进程所基于的物理RAM将不再相同(参考计数更新将迫使写页面上的副本尽快复制到子页面中)因为参考了这些值,所以增加了参考计数)。但是写时复制语义保留了虚拟内存地址,它们只是重新映射了底层物理页面,而CPython的id
正在报告(未更改的)虚拟内存地址。因此,对于介于-5到256之间的任何值,在id
版的子进程中,fork
的期望是相同的。您只会期望超出该范围的值会有差异,即使这样,如果运行时行为相同(可能也会在fork
上复制分配器状态;直到某些差异或不确定性会改变分配模式,分配的内存地址将继续遵循相同的模式。