Python多处理队列行为
我有以下代码:Python多处理队列行为,python,python-multiprocessing,Python,Python Multiprocessing,我有以下代码: def f(x, y): def _f(x, y, queue): res = get_data(x, y) queue.put(res) q = Queue() p = Process(target=_f, args=(x, y, q)) p.start() res = q.get() p.join() return res 它工作得很好。但是当我在p.join()之后执行res=q.
def f(x, y):
def _f(x, y, queue):
res = get_data(x, y)
queue.put(res)
q = Queue()
p = Process(target=_f, args=(x, y, q))
p.start()
res = q.get()
p.join()
return res
它工作得很好。但是当我在p.join()
之后执行res=q.get()
时,像这样:
q = Queue()
p = Process(target=_f, args=(x, y, q))
p.start()
p.join()
return q.get()
对于稍大的数据(例如JSON数组的几百个元素),它将挂起在p.join()
为什么会这样?您可能遇到了比赛条件。如果您想查看
多处理.Queue
源代码,您会注意到它使用了多处理.Pipe
和线程.threading
,以便在多处理.Process
实例之间进行通信。因此,当您调用Queue.put
时,实际上是在要求前面提到的线程使用连接将对象写入其他进程。调用Queue.get
时,实际上您正在使用通过Connection.recv
接收的数据,这些数据构成管道的另一端
现在,如果您深入研究多处理.Pipe
及其创建的连接
实例,您会发现它们使用操作系统低级接口来实现大部分功能。但是,通过使用此类接口,编写器必须遵守向连接提供的数据量上限。发送,而无需另一个进程
或线程
调用相应的连接。recv
在您的特定情况下,\u f
的过程在队列中结束。put(res)
返回(即,在您“请求”线程
写入res
之后)。唯一阻止进程完成的是挂起的连接;在那之后,它就可以自由行动了。如果对象很小并且遵守操作系统限制,Conneciton.send
将立即返回,整个过程将完成。另一方面,如果对象大于操作系统限制,Connection.send
将阻止等待Connection.recv
为剩余数据释放一些空间。但是,这永远不会发生,因为在调用进程.start
之后,您调用了进程.join
,它将一直阻止,直到进程
结束;只有在调用Connection.recv
后才会出现的结束;只有在Process.join
返回后才会发生的调用;我们关闭了我们的死锁链