如何使 multiprocessing.Array 进程在 python 中安全
How to make a multiprocessing.Array process safe in python
在构建 multiprocessing.Array
时,构造函数接受一个参数 lock
。默认设置为 True
据我了解,当 lock
标志设置为 True
时,由此创建的 multiprocessing.Array
应该是进程安全的。但是,我无法验证该行为。
我正在使用以下代码片段来验证行为:
import multiprocessing
def withdraw(balance):
for _ in range(10000):
balance[0] = balance[0] - 1
def deposit(balance):
for _ in range(10000):
balance[0] = balance[0] + 1
balance = multiprocessing.Array('f',[1000],lock=True) ### Notice lock=True passed explicitly
p1 = multiprocessing.Process(target=withdraw, args=(balance,))
p2 = multiprocessing.Process(target=deposit, args=(balance,))
p1.start()
p2.start()
p1.join()
p2.join()
print("Final balance = {}".format(balance[0]))
每次我 运行 此代码时,由于竞争条件影响 运行,我都会看到不同的最终结果。
你能帮我理解我在做什么吗and/or理解错了。根据我的理解,我发布的代码片段应该始终打印 1000
锁并不像你想象的那么原子。它只包装每个单独的读取或写入。我估计,在读取当前值和写入新值之间的间隙中,另一个进程已经跳入并保存了一个新值。保存此更改时,这些更改将被破坏。
有一篇针对 Multiprocessing.Value 的注释,它很有见地...
如果您将读取和写入都绑定到单个事务中,并使用所描述的 get_lock()
,它将满足您的期望...
def deposit(balance):
for _ in range(10000):
with balance.get_lock():
balance[0] = balance[0] + 1
def withdraw(balance):
for _ in range(10000):
with balance.get_lock():
balance[0] = balance[0] - 1
为了好玩和理解,您可以将 for
循环包裹在锁中并观察它按顺序执行 所有 取款,然后释放锁并执行 全部 存款依次为:
def withdraw(balance):
with balance.get_lock():
for _ in range(1, 1001):
balance[0] = balance[0] - 1
sys.stdout.write(f'w {balance[0]}\n')
在构建 multiprocessing.Array
时,构造函数接受一个参数 lock
。默认设置为 True
据我了解,当 lock
标志设置为 True
时,由此创建的 multiprocessing.Array
应该是进程安全的。但是,我无法验证该行为。
我正在使用以下代码片段来验证行为:
import multiprocessing
def withdraw(balance):
for _ in range(10000):
balance[0] = balance[0] - 1
def deposit(balance):
for _ in range(10000):
balance[0] = balance[0] + 1
balance = multiprocessing.Array('f',[1000],lock=True) ### Notice lock=True passed explicitly
p1 = multiprocessing.Process(target=withdraw, args=(balance,))
p2 = multiprocessing.Process(target=deposit, args=(balance,))
p1.start()
p2.start()
p1.join()
p2.join()
print("Final balance = {}".format(balance[0]))
每次我 运行 此代码时,由于竞争条件影响 运行,我都会看到不同的最终结果。
你能帮我理解我在做什么吗and/or理解错了。根据我的理解,我发布的代码片段应该始终打印 1000
锁并不像你想象的那么原子。它只包装每个单独的读取或写入。我估计,在读取当前值和写入新值之间的间隙中,另一个进程已经跳入并保存了一个新值。保存此更改时,这些更改将被破坏。
有一篇针对 Multiprocessing.Value 的注释,它很有见地...
如果您将读取和写入都绑定到单个事务中,并使用所描述的 get_lock()
,它将满足您的期望...
def deposit(balance):
for _ in range(10000):
with balance.get_lock():
balance[0] = balance[0] + 1
def withdraw(balance):
for _ in range(10000):
with balance.get_lock():
balance[0] = balance[0] - 1
为了好玩和理解,您可以将 for
循环包裹在锁中并观察它按顺序执行 所有 取款,然后释放锁并执行 全部 存款依次为:
def withdraw(balance):
with balance.get_lock():
for _ in range(1, 1001):
balance[0] = balance[0] - 1
sys.stdout.write(f'w {balance[0]}\n')