为什么以下多处理代码片段在多次运行时输出不同?



直观地说,输出应该始终为 15。但有时,它会生成 11 或 12 或其他东西。我尝试添加一些延迟,但没有解决问题。

from multiprocessing import Pool, Manager
import time
def func(dic, c):
dic['count'] += c
# time.sleep(0.1)
if __name__=="__main__":
d = Manager().dict()    # a manager to enable data sharing b
d['count'] = 0
args = [(d,1), (d,2), (d,3), (d,4), (d,5)]
pool = Pool(5)
pool.starmap(func, args)   
pool.close()
pool.join()
print(f'dic={d}')

增量运算符+=不是原子的。这意味着以这种方式使用是不安全的。调用此运算符时,将读取该值,然后将其替换为递增的值。如果第二个进程更改这两个操作之间的值,则更改将丢失。

看到这个答案: += 运算符在 Python 中是线程安全的吗?

你的问题是这个陈述:

dic['count'] += c

它读取字典,然后递增 c 并存储值,但这不是原子操作。另一个进程可能更改了读取和写入操作之间的字典,然后您的写入将"覆盖"操作之间发生的更改。

您可以通过传递锁并使用它来解决此问题:

def func(dic, lock, c):
with lock:
dic['count'] += c
# time.sleep(0.1)
if __name__=="__main__":
d = Manager().dict()    # a manager to enable data sharing b
l = Manager().Lock()
d['count'] = 0
args = [(d, l,1), (d,l,2), (d,l,3), (d,l,4), (d,l,5)]
pool = Pool(5)
pool.starmap(func, args)
pool.close()
pool.join()
print(f'dic={d}')

这可确保整个字典操作保持原子性。

最新更新