多处理计数器的输出很奇怪,使用锁

时间:2019-11-20 20:24:01

标签: python multiprocessing

我有一个简单的多处理示例。

我以此为基础创建了一个计数器,但是我发现工作中出现了奇怪的外观。

from multiprocessing import Pool, Value

counter = Value('i', 0)

def init(args):
    global counter
    counter = args

def analyze_data(args):
    global counter
    with counter.get_lock():
        counter.value += 1
    print(counter.value)
    return args * 10

if __name__ == '__main__':
    counter = Value('i', 0)
    inputs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]*10

    p = Pool(initializer = init, initargs = (counter, ),  processes=24)
    i = p.map_async(analyze_data, inputs, chunksize = 1)
    i.wait()
    print(i.get())

输出

1
33
4
5
6
7
...
...
6160
6262
64
65

我的期望值是1,2,3,4,5,6 ... 99,100(按顺序增加)

但是,这个输出很奇怪。

为什么会这样?

1 个答案:

答案 0 :(得分:1)

您必须在锁定块中打印计数器值,以避免在不受保护的打印和该值递增之间出现争用条件

with counter.get_lock():
    counter.value += 1
    print(counter.value)

其他:

    可以在打印锁之前,通过另一个等待锁 的进程更改
  • 值(解释双3
  • 打印语句可能以错误的顺序执行(解释6061的反转
  • 62次打印两次的事实是相关的(我必须承认我不知道会发生什么,但这是相同的根本原因)

复制或复制(但将打印保留在锁中会使显示更好,并避免输出混合。这解决了双值问题,但6061交换情况仍然可能发生) :

with counter.get_lock():
    counter.value += 1
    v = counter.value
print(v)