如何在两个进程之间共享数据?

Posted

技术标签:

【中文标题】如何在两个进程之间共享数据?【英文标题】:How to share data between two processes? 【发布时间】:2022-01-03 02:31:46 【问题描述】:

如何与另一个进程共享来自一个进程的值? 显然我可以通过多线程而不是多处理来做到这一点。 多线程对我的程序来说很慢。

我无法显示我的确切代码,所以我做了这个简单的例子。

from multiprocessing import Process
from threading import Thread
import time

class exp:
    def __init__(self):
        self.var1 = 0
            
    def func1(self):

        self.var1 = 5
        print(self.var1)

    def func2(self):

        print(self.var1) 


if __name__ == "__main__":

    #multithreading
    obj1 = exp()
    t1 = Thread(target = obj1.func1)
    t2 = Thread(target = obj1.func2)
    print("multithreading")
    t1.start()
    time.sleep(1)
    t2.start()

    time.sleep(3)


    #multiprocessing
    obj = exp()
    p1 = Process(target = obj.func1)
    p2 = Process(target = obj.func2)

    print("multiprocessing")
    p1.start()
    time.sleep(2)
    p2.start()

预期输出

multithreading
5
5
multiprocessing
5
5

实际输出

multithreading
5
5
multiprocessing
5
0

【问题讨论】:

这能回答你的问题吗? Sharing a complex object between processes? 这取决于您要共享的数据。我推荐使用队列docs.python.org/3/library/… 【参考方案1】:

有几种方法可以做到这一点:您可以使用shared memory、fifo 或message passing

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:

我知道有几票反对这个问题,但假设的重复问题的答案并不能真正解释 为什么 OP 的程序不能按原样运行 /em> 并且提供的解决方案不是我会建议的。因此:

让我们分析发生了什么。 obj = exp() 的创建由主进程完成。 exp.func1 的执行发生在不同的进程/地址空间,因此 obj 对象必须序列化/反序列化到该进程的地址空间。在那个新地址空间self.var1 遇到初始值 0,然后设置为 5,但只有在进程 p1 的地址空间中的 obj 对象的副本正在修改;存在于主进程中的该对象的副本未被修改。然后,当您启动进程p2 时,主进程的另一个obj 副本将发送到新进程,但self.var1 的值仍为0。

解决方案是让self.var1 成为multiprocessing.Value 的一个实例,multiprocessing.Value 是一个特殊变量,存在于所有进程都可以访问的共享内存中。请参阅docs。

from multiprocessing import Process, Value

class exp:
    def __init__(self):
        self.var1 = Value('i', 0, lock=False)

    def func1(self):

        self.var1.value = 5
        print(self.var1.value)

    def func2(self):

        print(self.var1.value)


if __name__ == "__main__":

    #multiprocessing
    obj = exp()
    p1 = Process(target = obj.func1)
    p2 = Process(target = obj.func2)

    print("multiprocessing")
    p1.start()
    # No need to sleep, just wait for p1 to complete
    # before starting p2:
    #time.sleep(2)
    p1.join()
    p2.start()
    p2.join()

打印:

multiprocessing
5
5

注意

使用共享内存解决这个特定问题比使用托管类高效得多,托管类由“关闭”注释引用。

将 5 赋值给self.var1.value原子操作,不需要是序列化操作。但是如果:

    我们正在执行非原子操作(需要多个步骤),例如 self.var1.value += 1 和: 多个进程并行执行此非原子操作,然后: 我们应该使用锁创建值:self.var1 = Value('i', 0, lock=True) 和: 更新锁控制下的值:with self.var1.get_lock(): self.var1.value += 1

【讨论】:

这回答了你的问题吗?

以上是关于如何在两个进程之间共享数据?的主要内容,如果未能解决你的问题,请参考以下文章

用于在两个进程之间共享数据的本地消息队列

如何在工作在同一共享内存区域的两个进程之间共享锁?

两个进程之间的命名共享内存

VC++共享数据段实现进程之间共享数据

Python3.x如何在进程之间共享数据库连接?

在 Dalvik 中的两个进程之间共享内存