繁体   English   中英

如何在 python 中使 multiprocessing.Array 进程安全

[英]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]))

每次运行此代码时,由于竞争条件影响运行,我都会看到不同的最终结果。

你能帮我理解我在做什么和/或理解错误吗? 根据我的理解,我发布的代码片段应该总是打印 1000

锁并不像你想象的那么原子。 它只包装每个单独的读取或写入。 我认为,在读取当前值和写入新值之间的间隙中,另一个进程已经跳入并保存了一个新值。 保存此更改时,这些更改将被破坏。

有一个针对Multiprocessing.Value的注释记录在案,这是有见地的......

Python 3.9 文档

如果您将读取和写入都绑定到单个事务中,并使用描述的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')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM