初始化为全局/局部变量时,多处理锁的工作方式不同
Posted
技术标签:
【中文标题】初始化为全局/局部变量时,多处理锁的工作方式不同【英文标题】:Multiprocessing lock working differently when initialized as global/local variable 【发布时间】:2021-11-22 15:19:16 【问题描述】:我正在使用多处理锁来确保文件访问多处理安全。根据我在哪里实例化我的锁,我会遇到意外的行为。
在下面的代码中,我有选项 1 和选项 2。根据我最终使用的选项,我会得到不同的结果。选项 1 产生预期的结果,其中锁阻止其他进程执行工作,直到具有锁的进程释放它。另一方面,选项 2 的行为就像锁不存在一样,几乎就像进程之间的锁不共享一样。下面也是两次运行的结果。我什至打印了 ID,但它们在进程之间是不同的值,所以我无法从中获得任何信息。为什么选项 1 能按预期工作,而选项 2 不能?
我正在使用 python 3.7.3
# file1.py
from file2 import ProcessManager
class Program:
def __init__(self):
self.manager = ProcessManager()
def start(self):
self.manager.run()
if __name__ == "__main__":
program = Program()
program.start()
# file2.py
import multiprocessing
from file3 import workingProcess
PACKAGE_LOCK = multiprocessing.Lock() # Option 1: Worked as expected
class ProcessManager:
def __init__(self):
self.proc = [] # list of processes
def run(self):
# package_lock = multiprocessing.Lock() Option 2: Would not work as expected
for i in range(3):
self.proc.append(
multiprocessing.Process(
target=workingProcess,
name=f"Process i",
args=(i, PACKAGE_LOCK,) # Option 1: Worked as expected
# args=(i, package_lock,) # Option 2: Would not work as expected
)
self.proc[-1].start()
# Do other stuff
# file3.py
def workingProcess(
process_idx,
package_lock
):
package_lock.acquire()
print(f"process_idx start time.time()")
print(f"process_idx ID id(package_lock)")
# Do Stuff
print(f"process_idx finished time.time()")
package_lock.release()
选项 1 结果
0 start 1633029033.4513052
0 ID 3096670642920
0 finished 1633029047.2527368
1 start 1633029047.2537322
1 ID 2665907335800
选项 2 结果:
0 start 1633028808.6572444
0 ID 1627297871128
1 start 1633028810.7597322
1 ID 2176530584688
2 start 1633028813.3802645
2 ID 2811978711784
0 finished 1633028823.7506292
【问题讨论】:
您在这两种情况下都创建了一个Lock
实例但在这两种情况下您都没有使用它(如调用acquire
和release
)。 即使start
您创建的进程也没有代码。 请参阅How to create a Minimal, Reproducible Example。另外,请根据 SO 指南使用您正在运行的平台标记您的问题。
@Booboo 抱歉,我没有复制部分代码。固定。
能否添加实例化ProcessManager
并调用run()
的代码?
@quamrana 添加了 run()
的调用位置以及 3 个组件如何通过 python 脚本分隔。
不知道为什么你以daemon
运行子进程,因为一旦你完成创建它们,主进程将退出,并终止所有子进程,我想这显然不是你想要的,所以不要'不了解您发布的输出。对我来说,两个锁在 python 3.8 下都按预期工作
【参考方案1】:
您发布的代码仍然不是Minimal, Reproducible Example;它缺少必需的导入语句,有多个语法错误,例如缺少关闭)
,multiprocessing
和mp
的使用不一致,testsuite
未定义等。
我已尝试清理代码,以便您的“选项 2”编译并运行,我认为没有问题(我已将类定义移至源代码的开头):
import multiprocessing as mp
import time
class ProcessManager:
def __init__(self):
self.proc = [] # list of processes
def run(self):
package_lock = mp.Lock()
for i in range(3):
self.proc.append(
mp.Process(
target=workingProcess,
name=f"Process i",
args=(i, package_lock,) # Option 2: Would not work as expected
)
)
self.proc[-1].start()
def workingProcess(
process_idx,
package_lock
):
package_lock.acquire()
print(f"process_idx start time.time()")
print(f"process_idx ID id(package_lock)")
# Do Stuff
print(f"process_idx finished time.time()")
package_lock.release()
class Program:
def __init__(self):
self.manager = ProcessManager()
def start(self):
self.manager.run()
if __name__ == "__main__":
program = Program()
program.start()
打印:
0 start 1633092270.5815103
0 ID 2430872331648
0 finished 1633092270.5845103
1 start 1633092270.5845103
1 ID 1643658290560
1 finished 1633092270.586511
2 start 1633092270.586511
2 ID 2922265716096
2 finished 1633092270.5885122
【讨论】:
以上是关于初始化为全局/局部变量时,多处理锁的工作方式不同的主要内容,如果未能解决你的问题,请参考以下文章