You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()强制终止进程,优先让子进程自然退出:

  1. 替换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())
    
  2. 若必须终止其他进程,可在子进程中显式等待put()操作完成后再标记结束:
    def foo(is_done, queue):
        queue.put(1)
        queue.close()
        queue.join_thread()  # 等待后台线程完成数据写入
        is_done.set()
    

内容的提问来源于stack exchange,提问作者jonemarian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:47:33