Python多进程并发代码是否本质串行?join()及执行疑问
先来看你写的这段多进程操作Queue的代码:
import time from multiprocessing import Process, Queue, Pool class QueueFun(): def writing_queue(self, work_tasks): while True: print("Writing to queue") work_tasks.put(1) time.sleep(.5) def read_queue(self, work_tasks): while True: print('Reading from queue') work_tasks.get() time.sleep(.5) if __name__ == '__main__': q = QueueFun() work_tasks = Queue() write_processes = [] read_processes = [] for i in range(0, 3): write_processes.append(Process(target=q.writing_queue, args=(work_tasks,))) for i in range(0, 3): read_processes.append(Process(target=q.read_queue, args=(work_tasks,))) for p in write_processes: p.start() for p in read_processes: p.start() print('Joining write_processes') for p in write_processes: print('Joining thread' , p) p.join() print('Joining read_processes') for p in read_processes: p.join()
针对你的三个疑问,咱们逐个拆解:
1. join()会让主进程等待目标进程结束,这段代码是否本质为串行执行?如何让读写进程真正并行?
首先纠正一个误解:你的代码里读写进程本身已经是并行运行的了!因为你先调用了所有write_processes的start(),又调用了所有read_processes的start(),这些进程一旦start()就会独立于主进程运行,互相之间是并行的。
那为什么你会有串行的错觉?问题出在主进程的join()顺序上:你让主进程先等待所有写进程结束,但你的写进程是while True的死循环,永远不会自己终止,所以主进程会一直卡在写进程的join()步骤,永远走不到后面的逻辑。但这并不影响已经启动的读写进程在后台并行干活——你能看到读写操作的输出,就说明它们确实在同时运行。
如果想让主进程不用卡死在join()上,同时又能正常管理这些进程,你可以给进程设置退出信号,比如用multiprocessing.Event()来控制循环终止:
# 举个简单的修改例子 def writing_queue(self, work_tasks, stop_event): while not stop_event.is_set(): print("Writing to queue") work_tasks.put(1) time.sleep(.5) # 主进程里 stop_event = Event() # 启动进程时把stop_event传进去 # 之后在需要退出的时候,调用stop_event.set(),所有进程就会结束循环,主进程就能正常join了
2. 为何"Joining read_processes"语句未被执行?
原因很直白:主进程在执行for p in write_processes: p.join()的时候,因为写进程是死循环,永远不会结束,所以主进程会一直阻塞在这里,根本没有机会执行到print('Joining read_processes')这一行代码。只有当所有写进程都终止后,主进程才会继续往下走,但你的写进程永远不会自己停,所以这句话永远打不出来。
3. join()是否仅阻塞主进程,不影响其他进程启动?
完全正确!join()的作用仅仅是阻塞调用它的进程(这里就是主进程),让它等待目标进程结束,对其他已经启动的进程没有任何影响。你代码里的读写进程都已经通过start()启动了,所以不管主进程有没有调用join(),它们都会正常并行运行——你能看到读写的交替输出,就是最好的证明。
内容的提问来源于stack exchange,提问作者Adrian

