Python多处理对象引用

问题描述

我不了解Python多处理模块。 我使用函数启动一个进程,并将传递和对象作为其参数。据我所知,它应该是那个物体的一模一样的复制品。但如果我尝试打印该对象的地址,则在每个过程中都是相同的。这怎么可能呢?地址不应该在每个过程中都不同吗?如果它在每个进程中都是同一个对象,为什么对它的更改不是全局的,而是每个进程的本地更改?

我的对象定义如下:

class MyClass():

    my_field = None

    def __init__():
        self.my_field = 0

和在单独进程中运行的函数

def function_to_run_in_process(some_object):
    print some_object

多个进程的结果如下:

<__main__.MyClass instance at 0x7f276419e5f0>
<__main__.MyClass instance at 0x7f276419e5f0>
<__main__.MyClass instance at 0x7f276419e5f0>

等等。

如果我尝试在进程内更改对象的某个字段,如下所示:

def function_to_run_in_process(some_object, process_lock):
   process_lock.acquire()
   some_object.some_field = some_object.some_field + 1
   process_lock.acquire()
   print some_object, 'with some_field = ', some_object.some_field, 'at address: ', hex(id(some_object.some_field))

我得到的结果类似于:

<__main__.MyClass instance at 0x7f276419e5f0>  with some_field = 1  at address  0xc5c428>
<__main__.MyClass instance at 0x7f276419e5f0>  with some_field = 1  at address  0xc5c428>
<__main__.MyClass instance at 0x7f276419e5f0>  with some_field = 1  at address  0xc5c428>
那么,如果传递的对象只是一个副本,为什么不仅对象有相同的地址,甚至它的字段也有相同的地址?如果它们相同,为什么对该字段的更改不可见?


解决方案

怎么可能?

每个进程都有自己的Virtual Address Space

每个进程中的地址不应该不同吗?

不。子进程正在继承其父进程的VAS。请参阅clone和fork。

如果它在每个进程中都是同一个对象,为什么对它的更改不是全局的,而是每个进程的本地更改?

VAS中的进程内存页将设置为COPY ON WRITE。只要页面没有更改,它们都将指向相同的物理内存,但是,如果进行了任何更改,该页面的VAS将映射到不同的位置。


这里有一篇关于进程内存管理的文章:http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/


如果您希望在进程之间共享状态,则可以共享内存或传递消息。多处理模块可以在共享内存页中创建PYTHON对象,具体说明here

不过,最好避免这样做,尤其是如果以上所有情况对您来说都是新闻。

相关文章