Python进程终止后queue.get()阻塞异常问题排查
多进程中调用queue.put()后仍出现queue.get()阻塞的原因
问题描述
我开发了一个多进程程序,逻辑是首个进程完成时终止其余所有进程。实际实现中用了multiprocessing.Event()标记结束状态,multiprocessing.Queue()存储返回值,但有时程序会卡在queue.get()方法,仿佛put()没执行完。
简化后的复现代码(仅一个子进程):
import multiprocessing def foo(is_done, queue): queue.put(1) is_done.set() if __name__ == "__main__": while True: is_done = multiprocessing.Event() queue = multiprocessing.Queue() p = multiprocessing.Process(target=foo,args=(is_done,queue)) p.start() is_done.wait() p.terminate() print(queue.get())
我本以为queue.put()之后才设置结束标记,进程会在值入队后才被终止,但实际还是出现阻塞。加短暂延迟后问题解决,想知道原因。
原因分析
核心问题:multiprocessing.Queue.put()并非立即完成
multiprocessing.Queue的实现依赖后台线程和IPC管道/共享内存:
- 调用
queue.put(1)时,数据先被存入用户态缓冲区,之后由后台线程负责将数据写入底层的IPC管道。 is_done.set()是同步执行的,但此时后台线程可能还没完成数据的实际写入操作。- 当调用
p.terminate()强制杀死子进程时,子进程内的后台线程会被直接终止——如果数据还没完全写入管道,主进程的queue.get()就会因队列中无数据而一直阻塞。
为什么延迟能解决问题?
短暂延迟给了子进程的后台线程足够时间,将缓冲区的数据彻底写入IPC管道,主进程的queue.get()自然就能读到数据。但这是临时 workaround,延迟时间无法在不同环境下精准适配。
正确解决方案
不要用terminate()强制终止进程,优先让子进程自然退出:
- 替换
p.terminate()为p.join(),等待子进程执行完所有逻辑后自然结束:import multiprocessing def foo(is_done, queue): queue.put(1) is_done.set() if __name__ == "__main__": while True: is_done = multiprocessing.Event() queue = multiprocessing.Queue() p = multiprocessing.Process(target=foo,args=(is_done,queue)) p.start() is_done.wait() p.join() # 等待子进程自然结束,确保后台线程完成写入 print(queue.get()) - 若必须终止其他进程,可在子进程中显式等待
put()操作完成后再标记结束:def foo(is_done, queue): queue.put(1) queue.close() queue.join_thread() # 等待后台线程完成数据写入 is_done.set()
内容的提问来源于stack exchange,提问作者jonemarian
相关产品推荐
相关产品推荐

