簡體   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