【问题标题】:Python multithreading doesn't use common memory when the parent object is created inside a process在进程内创建父对象时,Python 多线程不使用公共内存
【发布时间】:2016-09-22 08:28:26
【问题描述】:

我正在尝试实现一个线程,该线程将在后台运行并执行一项任务。这是我的代码,它给出了预期的输出。

代码 1:

from time import sleep
from threading import Thread

class myTest( ):
    def myThread( self ):
        while True:
            sleep( 1 )
            print self.myList.keys( )
            if 'exit' in self.myList.keys( ):
                break
        return

    def __init__( self ):
        self.myList = { } 
        self.thread = Thread( target = self.myThread, args = (  ) )
        self.thread.start( )
        return

    def myFun( self ):
        i = 0
        while True:
            sleep( 0.5 )
            self.myList[ i ] = i
            i += 1
            if i > 5 :
                self.myList[ 'exit' ] = ''
                break
        return

x = myTest( )
x.myFun( )

输出 1:

[0]
[0, 1, 2]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 5, 'exit']

在我创建多进程环境并在新的子进程中创建此对象的那一刻,线程无法访问公共内存并且字典myList 在线程中保持空白。这是代码。

代码 2:

from time import sleep
from threading import Thread
from multiprocessing import Process

class myTest( ):
    def myThread( self ):
        while True:
            sleep( 1 )
            print "myThread", self.myList.keys( )
            if 'exit' in self.myList.keys( ):
                break
        return

    def __init__( self ):
        self.myList = { } 
        self.thread = Thread( target = self.myThread, args = (  ) )
        self.thread.start( )
        self.i = 0
        return

    def myFun( self ):
        self.myList[ self.i ] = self.i
        self.i += 1
        if self.i > 5 :
            self.myList[ 'exit' ] = ''
            return 'exit'
        print 'myFun', self.myList.keys( )
        return

class myProcess( Process ):
    def __init__( self ):
        super( myProcess, self ).__init__( )
        self.myObject = myTest( )
        return

    def run(self):
        while True:
            sleep( 0.5 )
            x = self.myObject.myFun( )
            if x == 'exit':
                break
        return

x = myProcess( )
x.start( )

输出 2:

myFun [0]
myThread []
myFun [0, 1]
myFun [0, 1, 2]
myThread []
myFun [0, 1, 2, 3]
myFun [0, 1, 2, 3, 4]
myThread []
myThread []
myThread []
... ... ...
... ... ...

在第一个代码中,对象是在 Python 进程(虽然是主进程)中创建的。在第二个代码中,对象是在 Python 的一个子进程中创建的,所有的事情都发生了,应该和第一个一样。

  1. 谁能解释为什么在第二个代码中,线程无法使用父对象的共享内存?
  2. 我想要code 2 中的output 1,即强制线程使用父对象的共享公共内存。我需要进行哪些修改?

【问题讨论】:

  • 当您向第二个进程发送垃圾邮件时,会创建第一个进程的副本,因此在第二个进程中发送垃圾邮件的线程只能访问该进程堆栈
  • @DanielSanchez 感谢您指出错误。更改了对象创建的位置,它可以工作。您可以将其添加为答案以便我接受吗?
  • 很高兴它有帮助:)
  • “有点像”stackoverflow.com/questions/27809586/… 的副本
  • @temoto 这里提到的问题有点混乱。由于整个类都继承了多处理,因此想法是,在构造函数中初始化的任何内容都将被共享,而不是共享。顺便说一句,谢谢。

标签: python multithreading multiprocessing


【解决方案1】:

当您生成第二个进程时,会创建第一个进程的副本,因此在第二个进程中生成的线程只能访问该进程堆栈。

在 code2 中,myTest 的对象是在构造函数 (__init__) 中创建的,因此它不会与生成的进程 run 共享相同的内存。只需将对象创建的位置从构造函数更改为run,创建的对象就会成为衍生进程内存的一部分。

【讨论】:

    【解决方案2】:

    分叉的进程在fork() 的时刻看到父级内存的快照。当父母或孩子改变一个位时,他们的内存映射就会不同,一个看到它改变了什么,另一个看到旧状态。我在这个答案中更详细地解释了这个理论:https://stackoverflow.com/a/29838782/73957

    如果您想共享内存 [更改],则必须隐式执行。在 Python 中,一种简单的方法是multiprocessing.{Queue,Value,Array},参见https://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2015-05-05
      相关资源
      最近更新 更多