Python 子流程已完成,但仍不执行';t终止,导致死锁

Python 子流程已完成,但仍不执行';t终止,导致死锁,python,debugging,python-3.x,deadlock,multiprocessing,Python,Debugging,Python 3.x,Deadlock,Multiprocessing,好的,因为目前还没有答案,所以我觉得这样做并不太糟糕。 虽然我仍然对幕后到底发生了什么导致这个问题感兴趣,但我最迫切的问题是更新2中指定的问题。那些 JoinableQueue和Manager().Queue()之间有什么区别(什么时候应该使用一个而不是另一个?)。重要的是,在这个例子中,用一个替换另一个安全吗 在下面的代码中,我有一个简单的进程池。每个进程都被传递到进程队列(pq)以从中提取要处理的数据,以及返回值队列(rq)以将处理的返回值传递回主线程。如果我不将其附加到返回值队列中,它就

好的,因为目前还没有答案,所以我觉得这样做并不太糟糕。 虽然我仍然对幕后到底发生了什么导致这个问题感兴趣,但我最迫切的问题是更新2中指定的问题。那些

JoinableQueue
Manager().Queue()
之间有什么区别(什么时候应该使用一个而不是另一个?)。重要的是,在这个例子中,用一个替换另一个安全吗


在下面的代码中,我有一个简单的进程池。每个进程都被传递到进程队列(
pq
)以从中提取要处理的数据,以及返回值队列(
rq
)以将处理的返回值传递回主线程。如果我不将其附加到返回值队列中,它就会工作,但一旦我附加,由于某种原因,进程就会被阻止停止。在这两种情况下,进程
run
方法返回,因此不会
put
在返回队列阻塞上,但在第二种情况下,进程本身不会终止,因此当我
join
在进程上时,程序会死锁。为什么会这样

更新:

  • 它似乎与队列中的项目数量有关。

    至少在我的机器上,我最多可以有6570个项目在队列中,它实际上可以工作,但如果超过这个,它就会死锁

  • 它似乎适用于
    Manager().Queue()


    无论是对
    JoinableQueue
    的限制,还是仅仅是我误解了这两个对象之间的差异,我发现如果我用
    Manager().Queue()
    替换返回队列,它都能正常工作。它们之间有什么区别,什么时候应该使用其中一个

  • 如果我使用的是
    rq


    Oop,则不会发生错误。这里有一个答案,当我评论它的时候,它消失了。无论如何,它说的一件事是质疑,如果我添加一个消费者,这个错误是否仍然发生。我已经试过了,答案是,没有

    它提到的另一件事是,这句话可能是解决问题的关键。在提到可连接队列时,它说:

    。。。用于计算未完成任务数的信号量可能 最终溢出引发了一个异常



  • 示例输出,不使用返回队列:

    ++ Proc-1
    ++ Proc-2
    ++ Proc-3
    ++ Proc-4
    == Proc-4
    == Proc-3
    == Proc-1
    ?? [<Proc(Proc-1, started)>, <Proc(Proc-2, started)>, <Proc(Proc-3, started)>, <Proc(Proc-4, started)>]
    == Proc-2
    ?? [<Proc(Proc-1, stopped)>, <Proc(Proc-2, started)>, <Proc(Proc-3, stopped)>]
    -- Proc-3
    ?? [<Proc(Proc-1, stopped)>, <Proc(Proc-2, started)>]
    -- Proc-2
    ?? [<Proc(Proc-1, stopped)>]
    -- Proc-1
    ** complete
    -- Proc-4
    
    ++Proc-1
    ++Proc-2
    ++Proc-3
    ++Proc-4
    ==Proc-4
    ==Proc-3
    ==Proc-1
    ?? [, , ]
    ==Proc-2
    ?? [, ]
    --Proc-3
    ?? [, ]
    --Proc-2
    ?? []
    --Proc-1
    **完整的
    --Proc-4
    

    使用返回队列的示例输出:

    ++ Proc-1
    ++ Proc-2
    ++ Proc-3
    ++ Proc-4
    == Proc-2
    == Proc-4
    == Proc-1
    ?? [<Proc(Proc-1, started)>, <Proc(Proc-2, started)>, <Proc(Proc-3, started)>, <Proc(Proc-4, started)>]
    == Proc-3
    # here it hangs
    
    ++Proc-1
    ++Proc-2
    ++Proc-3
    ++Proc-4
    ==Proc-2
    ==Proc-4
    ==Proc-1
    ?? [, , ]
    ==Proc-3
    #挂在这里
    
    来自:

    警告

    如上所述,如果子进程已将项放入队列(并且未使用JoinableQueue.cancel_join_thread()),则在所有缓冲项都刷新到管道之前,该进程不会终止

    这意味着,如果您尝试加入该进程,则可能会出现死锁,除非您确定已放入队列的所有项目都已被使用。类似地,如果子进程是非守护进程,则父进程在尝试加入其所有非守护子进程时可能会挂起退出

    请注意,使用管理器创建的队列没有此问题。参见编程指南

    因此JoinableQueue()使用一个管道,并将在关闭之前等待,直到它可以刷新所有数据

    另一方面,Manager.Queue()对象使用完全不同的方法。 管理者正在运行一个单独的进程,该进程立即接收所有数据(并将其存储在内存中)

    管理者提供了一种创建可在不同流程之间共享的数据的方法。管理器对象控制管理共享对象的服务器进程。其他进程可以使用代理访问共享对象

    队列([maxsize]) 创建共享Queue.Queue对象并为其返回代理


    可能与之相关:@J.F.Sebastian。它可能是,但这似乎是在说它在
    put
    上阻塞,所有我的
    run
    在阻塞和
    put
    之前的返回都只发生在
    run
    内,所以我的
    put
    不能被阻塞。
    ++ Proc-1
    ++ Proc-2
    ++ Proc-3
    ++ Proc-4
    == Proc-2
    == Proc-4
    == Proc-1
    ?? [<Proc(Proc-1, started)>, <Proc(Proc-2, started)>, <Proc(Proc-3, started)>, <Proc(Proc-4, started)>]
    == Proc-3
    # here it hangs