使用json文件时,多处理锁不会阻止争用条件

2024-08-31 09:10:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个json文件,其中只有一个对象:

incme.json

{
    "value": 0
}

我正在尝试使用multiprocessingProcessPoolExecutor更新它,并使用multiprocessing.Lock防止竞争条件:

from concurrent.futures import ProcessPoolExecutor
import multiprocessing as mp
import numpy as np
import json

def inc(tup):   
    lock, ignoreme = tup
    with lock:
        with open('incme.json', 'r') as f:
            data = json.load(f)
    print (data)
    data['value'] += 1
    with lock:
        with open('incme.json', 'w') as f:
            json.dump(data, fp=f, indent=4)
    ignoreme += 1
        
if __name__ == '__main__':
    m = mp.Manager()
    lock = m.Lock()
    
    NUMBER_OF_CPUS = mp.cpu_count()
    # use up to +++ of the cpu`s available 
    USE_UP_TO = 0.5
    
    inc((lock, 1))
    
    with ProcessPoolExecutor(max_workers=np.uint16(NUMBER_OF_CPUS * USE_UP_TO)) as executor:
        for i in range(100):    
            print('inc:')
            executor.submit(inc, ((lock, 1)))

当上面的代码运行时,它将使value成为44或低于101的值

以这种方式使用锁时:

def inc(tup):   
    lock, ignoreme = tup
    with lock:
        with open('incme.json', 'r') as f:
            data = json.load(f)
        print (data)
       data['value'] += 1
        with open('incme.json', 'w') as f:
            json.dump(data, fp=f, indent=4)
    ignoreme += 1

value变为101,但现在它不异步工作。 这是什么原因造成的?它是否与IO相关的任务有关


Tags: importjsonlockdatavalueaswithmp
1条回答
网友
1楼 · 发布于 2024-08-31 09:10:28

您的锁似乎保护得太少。是的,您以原子方式读取,您以原子方式写入,但您不以原子方式执行读取增量写入序列。例如,没有什么可以阻止所有100个进程读取0,然后每个进程将1添加到0,然后每个进程将1作为新值写入

相反,请尝试删除第二个with lock:语句,并缩进print()和increment语句,以便以原子方式完成整个读增量写序列

编辑

哎呀!我知道你已经试过了,而且已经发现它有效了。所以我对你为什么认为原来的方式“应该”起作用感到困惑。显然不应该;-)

相关问题 更多 >