为什么配置lock=True的multiprocessing.Value不是进程安全的?
问题原因分析
你代码运行结果不符合预期的核心原因是 n.value += 1属于多步复合操作,multiprocessing.Value的内置锁仅能保障单次读、写操作的进程安全,无法自动覆盖复合操作的完整执行流程。
n.value += 1在实际执行时会拆分为3个独立步骤:
- 第一步:获取
Value的内置锁,读取当前存储的数值,读取完成后立即释放锁 - 第二步:在当前进程的本地内存空间中,对读取到的数值执行+1计算
- 第三步:再次获取
Value的内置锁,将计算后的新数值写入,写入完成后释放锁
因为第一步和第三步之间没有锁保护,两个进程完全可能同时读取到同一个数值,各自计算后再先后写入,最终就会出现累加次数丢失的情况,导致最终结果小于20000且每次运行结果不一致。
修复方案
要解决这个问题,你需要手动获取Value的内置锁,将整个复合操作全程包裹在锁的保护范围内,修改后的foo函数代码如下:
def foo(n): for i in range(10000): # 手动加锁保证读-计算-写全程原子 with n.get_lock(): n.value += 1
修改后运行代码,输出结果就会稳定为20000。
补充说明:multiprocessing.Value相比RawValue的内置锁作用是保证单次读、写操作不会出现数据撕裂(比如读到一半被其他进程修改的异常值),并不会自动为多步组合操作加锁,这是常见的使用误区。
内容的提问来源于stack exchange,提问作者David McNamee
相关产品推荐
相关产品推荐

