Python-增加计数会产生意外结果

问题描述

在下面的代码中,我期望print('q.count',q.count)为2,因为count是一次使用q = QueueFun()初始化的变量,然后在read_queue方法中递增,而不是{{1} }打印0。在多进程之间共享计数器的正确方法是什么?

完整代码

print('q.count',q.count)

解决方法

与线程不同,不同的进程具有不同的地址
空格:它们彼此之间不共享内存。写作
在一个过程中将其更改为变量将不会更改(非共享)
另一个过程中的变量。

在原始示例中,最后的计数为0,因为
主要流程从未改变过(不管其他什么
产生的进程)。

使用Queue在进程之间进行通信可能更好。
如果确实需要,可以使用Value或Array:

17.2.1.5. Sharing state between processes

如上所述,在进行并行编程时,通常 最好尽量避免使用共享状态。这是 使用多个进程时尤其如此。

但是,如果您确实确实需要使用一些共享数据,则 多重处理提供了两种方法。

共享内存可以使用Value或数据存储在共享内存映射中 数组。
...
这些共享对象将是进程和线程安全的。

multiprocessing.Value

像+ =这样的涉及读写的操作不是原子操作。

问题代码的略微修改版本:

from multiprocessing import Process,Queue,Value

class QueueFun():
    def __init__(self):
        self.readCount = Value('i',0)
        self.writeCount = Value('i',0)
    
    def write_queue(self,work_tasks,MAX_SIZE):
        with self.writeCount.get_lock():
            if self.writeCount != MAX_SIZE:
                self.writeCount.value += 1
                work_tasks.put(1)
    
    def read_queue(self,MAX_SIZE):
        with self.readCount.get_lock():
            if self.readCount.value != MAX_SIZE:
                self.readCount.value += 1
                work_tasks.get()

if __name__ == '__main__':
    q = QueueFun()
    MAX_SIZE = 2
    work_tasks = Queue()
    
    write_processes = []
    for i in range(MAX_SIZE):
        write_processes.append(Process(target=q.write_queue,args=(work_tasks,MAX_SIZE)))
    for p in write_processes: p.start()
    
    read_processes = []
    for i in range(MAX_SIZE):
        read_processes.append(Process(target=q.read_queue,MAX_SIZE)))
    for p in read_processes: p.start()
    
    for p in read_processes: p.join()
    for p in write_processes: p.join()
    
    print('q.writeCount.value',q.writeCount.value)
    print('q.readCount.value',q.readCount.value)

注意:从多个过程打印到标准输出,
会导致输出混乱(不同步)。