Python多进程中不同进程的对象为何拥有相同ID?
多进程中对象ID相同的原因分析
测试代码
test.py
import multiprocessing import time class A: def __action(self): print("another process:") print(id(self)) def run(self): print("this process") print(id(self)) p = multiprocessing.Process(target=self.__action, daemon=True) p.start() a = A() print("main") print(id(a)) a.run() time.sleep(3)
运行结果
$ python3 test.py main 140643898766000 this process 140643898766000 another process: 140643898766000
官方文档相关说明
如上所述,进行并发编程时通常应尽可能避免使用共享状态,在多进程场景下尤其如此。
不过,如果确实需要使用共享数据,multiprocessing提供了几种实现方式:
共享内存
可使用Value或Array将数据存储在共享内存映射中。
问题
按照文档所述,似乎只有通过显式定义Value/Array才能让两个进程拥有相同对象,但为何当前不同进程中的A对象却拥有相同的id?
解答
这是对Python中id()函数和多进程内存模型的误解:
id()的本质:id(obj)返回的是对象在当前进程内存空间中的地址,这个地址值只在当前进程内有意义——不同进程的内存空间完全隔离,不存在地址复用的冲突限制。- 子进程的内存复制:在Unix/Linux系统中,multiprocessing默认用
fork创建子进程,fork会复制父进程的整个内存空间到子进程。父进程中的A对象会在子进程中生成一个完全独立的副本,这个副本在子进程内存中的地址刚好和父进程中原对象的地址数值相同——这只是巧合,并非两个进程共享同一个对象。 - 和官方文档的区别:官方文档说的"共享对象"是指两个进程访问同一块物理内存中的数据,也就是真正的状态共享,修改一个进程中的对象会影响另一个进程。而你看到的相同ID只是地址数值重复,两个对象完全独立——你可以测试在子进程的
__action中修改self的属性,父进程中对应的属性不会有任何变化。
简单说:ID数值相同不代表是同一个对象,只是两个进程里的不同对象刚好在各自的内存空间里占了同一个地址位置而已。
内容的提问来源于stack exchange,提问作者atline
相关产品推荐
相关产品推荐

