You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

multiprocessing.Process下线程无法更新实例属性的问题求助

问题分析与解决方案

我希望并行运行多个Foo类实例,通过Redis更新实例的value属性。每个实例启动后台线程监听Redis变化,但执行redis-cli set value 9后,线程检测到变化并打印提示,但实例的value属性并未更新,run方法始终输出初始值5。

原代码:

import time
import threading
import redis


class Foo:
    def __init__(self, name: str):
        self.name = name

        self.redis_client = redis.Redis(host="localhost", port=6379)
        self.value = 5

        self.update_thread = threading.Thread(target=self.update, daemon=True)
        self.update_thread.start()

    def update(self):
        while True:
            new_value = int(self.redis_client.get("value"))
            if new_value != self.value:
                print("new value detected {}".format(new_value))
                self.value = new_value
            time.sleep(2)

    def run(self):
        while True:
            print("{}: Value: {}".format(self.name, self.value))
            time.sleep(2)


if __name__ == "__main__":
    import multiprocessing

    foo1 = Foo(name="foo1")
    foo2 = Foo(name="foo2")

    process1 = multiprocessing.Process(target=foo1.run)
    process2 = multiprocessing.Process(target=foo2.run)

    process1.start()
    process2.start()

控制台输出:

foo1: Value: 5
foo2: Value: 5
new value detected 9
new value detected 9
foo1: Value: 5
foo2: Value: 5

问题根源

  • 父进程创建foo1、foo2实例时,已在父进程中启动它们的update线程,这些线程仅在父进程内存空间运行,更新的是父进程中实例的value。
  • 使用multiprocessing.Process传递foo1.run时,Python会将父进程中的foo1实例序列化后复制到子进程,子进程得到的是完全独立的实例副本,与父进程实例的内存空间完全隔离。
  • 子进程的实例副本不会继承父进程的update线程(反序列化过程不会重新执行__init__中的线程启动逻辑),父进程的update线程也无法修改子进程副本的属性。
  • 控制台中new value detected 9是父进程里的update线程打印的,和子进程中的实例没有任何关系,子进程副本的value始终是初始的5。

解决方案

最直接的修复方式是让每个子进程独立创建Foo实例,这样每个子进程的实例会自己启动update线程,监听Redis并更新自身的value属性。

修改后的代码:

import time
import threading
import redis


class Foo:
    def __init__(self, name: str):
        self.name = name

        self.redis_client = redis.Redis(host="localhost", port=6379)
        self.value = 5

        self.update_thread = threading.Thread(target=self.update, daemon=True)
        self.update_thread.start()

    def update(self):
        while True:
            new_value = int(self.redis_client.get("value"))
            if new_value != self.value:
                print("new value detected {}".format(new_value))
                self.value = new_value
            time.sleep(2)

    def run(self):
        while True:
            print("{}: Value: {}".format(self.name, self.value))
            time.sleep(2)


if __name__ == "__main__":
    import multiprocessing

    def start_foo(name):
        # 子进程内创建实例,启动自身的update线程
        foo = Foo(name=name)
        foo.run()

    process1 = multiprocessing.Process(target=start_foo, args=("foo1",))
    process2 = multiprocessing.Process(target=start_foo, args=("foo2",))

    process1.start()
    process2.start()

效果验证

执行redis-cli set value 9后,控制台会输出:

foo1: Value: 5
foo2: Value: 5
new value detected 9
new value detected 9
foo1: Value: 9
foo2: Value: 9

此时每个子进程的实例都能正确更新value属性并打印最新值。

内容的提问来源于stack exchange,提问作者birdalugur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 11:53:18