`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()
THE END
二维码