在下面的代码中,我希望print('q.count' , q.count)
是2,因为count
是一个变量,使用q = QueueFun()
初始化一次,然后在read_queue
方法中递增,而print('q.count' , q.count)
打印0。在多进程之间共享计数器的正确方法是什么?
完整代码:
from multiprocessing import Process, Queue, Pool, Lock
class QueueFun():
def __init__(self):
self.count = 0
self.lock = Lock()
def write_queue(self, work_tasks, max_size):
for i in range(0, max_size):
print("Writing to queue")
work_tasks.put(1)
def read_queue(self, work_tasks, max_size):
while self.count != max_size:
self.lock.acquire()
self.count += 1
self.lock.release()
print('self.count' , self.count)
print('')
print('Reading from queue')
work_tasks.get()
if __name__ == '__main__':
q = QueueFun()
max_size = 1
work_tasks = Queue()
write_processes = []
for i in range(0,2):
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(0, 2):
read_processes.append(Process(target=q.read_queue,
args=(work_tasks,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.count' , q.count)
与线程不同,不同的进程有不同的地址
空间:它们彼此不共享内存。将
写入一个进程中的变量不会更改另一个进程的(非共享的(
变量。
在最初的示例中,计数最后为0,因为
主进程从未更改它(无论其他
派生进程做了什么(。
可能最好使用Queue在进程之间进行通信
如果确实需要,可以使用Value或Array:
17.2.1.5进程之间的共享状态
如上所述,在进行并发编程时最好尽可能避免使用共享状态。这是尤其是在使用多个过程时更是如此。
但是,如果您确实需要使用一些共享数据,那么多处理提供了几种方法。
共享内存数据可以使用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, work_tasks, 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,
args=(work_tasks,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)
注意:从多个进程打印到标准输出,
可能会导致输出混淆(不同步(。