`multiprocessing.Process` 正在修改他们不应该访问的非共享变量

进程正在改变他们不应该改变的东西。

AWorker有一个状态变量 (an mp.Value)。此值设置为-1,并且它 (the Worker)1在循环中将其更改为。

然而,这似乎是可以重置该值-1由产卵第二Worker,即使这股没有与原来的对。这似乎应该是不可能的。

行为:

当第二个工作器Worker启动时,第一个工作器 ( self.state.value)的状态被重置为-1。这被捕获,我们打印出发现错误。

代码:

import multiprocessing as mp
import time


class Worker:
    def __init__(self, tag, service_state) -> None:
        self.tag = tag
        self.local_state = int(service_state.value)
        self.state = service_state
        self.run_work_loop()

    def run_work_loop(self) -> None:
        print(f"[{self.tag}] Running... {self.state.value} {self.local_state}")
        while True:
            if self.state.value != self.local_state:
                print(f"[{self.tag}] Illegal change. Shared state: {self.state.value} Local State: {self.local_state}")
                break

            elif self.state.value == -1:
                self.state.value = self.local_state = 1
                print(f"[{self.tag}] Set Shared State: {self.state.value} Local State: {self.local_state}.")


if __name__ == "__main__":
    mp.Process(target=Worker, args=("A", mp.Value('i', -1))).start()
    time.sleep(.03)
    mp.Process(target=Worker, args=("B", mp.Value('i', -1))).start()


输出:

[A] Running... -1 -1
[A] Set Shared State: 1 Local State: 1.
[A] Illegal change. Shared state: -1 Local State: 1
[B] Running... -1 -1
[B] Set Shared State: 1 Local State: 1.

回答

问题是您正在创建Value立即超出父进程范围的实例,这使它们被垃圾收集。由于Python 为multiprocessing.Valueobjects分配内存的方式,第二个Value最终使用与第一个完全相同的共享内存位置Value,这意味着第二个最终会踩到第一个。你可以做一些实验来看看这个。例如,这不会打印警告:

if __name__ == "__main__":
mp.Process(target=Worker, args=("A", mp.Value('i', -1))).start()
time.sleep(.03)
a = mp.Value('i', 1)
mp.Process(target=Worker, args=("B", mp.Value('i', -1))).start()

Value我们分配到a被初始化为1,这将覆盖匿名Value,我们通过处理“A”。因为我们用 1 覆盖它,所以不会打印非法状态消息。如果我们改为将其初始化为任何其他值,您将再次看到警告。这将打印关于 -2, 的非法状态消息,例如:

if __name__ == "__main__":
mp.Process(target=Worker, args=("A", mp.Value('i', -1))).start()
time.sleep(.03)
a = mp.Value('i', -2)
mp.Process(target=Worker, args=("B", mp.Value('i', -1))).start()

您的代码应该真正将Value您创建的实例保存为父进程中的局部变量,以避免此问题,并且因为创建您实际上并未共享的共享值毫无意义。像这样:

if __name__ == "__main__":
a = mp.Value('i', -1)
mp.Process(target=Worker, args=("A", a)).start()
time.sleep(.03)
b = mp.Value('i', -1)
mp.Process(target=Worker, args=("B", b)).start()

以上是`multiprocessing.Process` 正在修改他们不应该访问的非共享变量的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>