【问题标题】:python sharing singleton object between child processespython在子进程之间共享单例对象
【发布时间】:2019-02-05 15:39:10
【问题描述】:

我知道进程在 python 中不共享相同的上下文。但是单例对象呢?我能够让子进程与父进程共享相同的内部对象,但我无法理解如何。下面的代码有问题吗?

这可能是对this stackoverflow question 的跟进。

这是我的代码:

Singleton.py:


import os

class MetaSingleton(type):
     _instances = {}

def __call__(cls, *args, **kwargs):
    if cls not in cls._instances:
        cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
    return cls._instances[cls]

class Singleton:
   __metaclass__ = MetaSingleton

   def __init__(self):
       self.key="KEY TEST"
       print "inside init"

   def getKey(self):
       return self.key

  def setKey(self,key1):
       self.key = key1

  process_singleton.py:


  import os
  from Singleton import Singleton

  def callChildProc():
       singleton = Singleton()
       print ("singleton key: %s"%singleton.getKey())

  def taskRun():
       singleton = Singleton()
       singleton.setKey("TEST2")
       for i in range(1,10):
           print ("In parent process, singleton key: %s" %singleton.getKey())
        try:
           pid = os.fork()
        except OSError,e:
           print("Could not create a child process: %s"%e)

        if pid == 0:
            print("In the child process that has the PID %d"%(os.getpid()))
           callChildProc()
           exit()

       print("Back to the parent process")

 taskRun()

【问题讨论】:

  • 哪个操作系统?在类似 linux 的系统上,分叉的子进程具有父进程的写时复制视图。孩子看到分叉之前父母设置的任何内容。
  • 哦,我明白了。这是否意味着,一旦启动子进程,如果父进程继续并更改某些值(例如,上面示例中的“键”),子进程会看到它吗?这是在linux上。本质上,单例行为是否也保留在子进程中?
  • 我写了一个答案,希望 (?!) 解释它是如何工作的。

标签: python process singleton fork


【解决方案1】:

在分叉系统上,子进程具有父内存空间的写入时副本视图。进程使用虚拟内存,并且在分叉之后两个进程虚拟空间都指向相同的物理 RAM。在写入时,复制物理页面并重新映射虚拟内存,以便不再共享内存位。这种延迟复制通常比在分叉处克隆内存空间要快。

结果是父母或孩子都看不到对方的变化。由于您在 fork 之前设置了单例,因此父级和子级都看到相同的值。

这是一个简单的示例,我使用time.sleep 来控制父母和孩子何时进行私人更改:

import multiprocessing as mp
import time

def proc():
    global foo
    time.sleep(1)
    print('child foo should be 1, the value before the fork:', foo)
    foo = 3 # child private copy


foo = 1 # the value both see at fork
p = mp.Process(target=proc)
p.start()
foo = 2 # parent private copy
time.sleep(2)
print('parent foo should be 2, not the 3 set by child:', foo)

运行时:

child foo should be 1, the value before the fork: 1
parent foo should be 2, not the 3 set by child: 2

【讨论】:

    猜你喜欢
    • 2022-11-28
    • 2012-07-22
    • 1970-01-01
    • 2020-12-05
    • 2017-02-02
    • 1970-01-01
    • 2023-03-24
    • 2021-10-21
    • 2016-02-05
    相关资源
    最近更新 更多