我有这段代码:
<script>
hbspt.forms.create({
portalId: '2089699',
formId: '287337b2-e8a6-4eaa-b293-bbd3d3622d8a'
});
</script>
完美无缺。但是当我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
之后res = q.get()
这样做时:
p.join()
对于有些大的数据(例如,数百个JSON数组元素),它将挂起q = Queue()
p = Process(target=_f, args=(x, y, q))
p.start()
p.join()
return q.get()
。
为什么?
答案 0 :(得分:0)
您可能正在遇到比赛状况。如果您想查看multiprocessing.Queue
的来源,您会注意到它使用multiprocessing.Pipe
和threading.Thread
来在multiprocessing.Process
实例之间进行通信。因此,当您调用Queue.put
时,实际上是在要求上述线程使用Process
创建的Connection.send
将对象写入其他Pipe
。当您致电Queue.get
时,实际上是在消费通过Connection.recv
接收的数据,这些数据构成了Pipe
的另一端。
现在,如果深入研究multiprocessing.Pipe
和它创建的Connection
实例,您会发现它们使用OS低级接口来实现其大多数功能。但是,通过使用这样的接口,编写者必须遵守一个上限,即它可以向Connection.send
馈送多少数据,而无需另外的Process
或Thread
调用各自的Connection.recv
。
在您的特定情况下,Process
的{{1}}会在_f
返回时立即结束(即,在您“问” queue.put(res)
以写{{1 }})。阻止Thread
完成的唯一事情是待处理的res
;之后,它是免费的。如果对象较小并且遵守操作系统限制,则Process
将立即返回,并且整个过程将完成。另一方面,如果对象大于操作系统限制,则Connection.send
将阻止等待Conneciton.send
为剩余数据释放一些空间。但是,这永远不会发生,因为在您调用Connection.send
之后立即调用Connection.recv
,它将阻塞直到Process.start
结束;只有在您致电Process.join
之后才会出现的结尾;仅在Process
返回之后才会发生的呼叫;然后我们关闭了死锁链。