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