9

以下代码不打印"here"。问题是什么?我在我的两台机器(Windows 7、Ubuntu 12.10)和 http://www.compileonline.com/execute_python_online.php上都对其进行了测试, 它并非"here"在所有情况下都打印出来。

from multiprocessing import Queue, Process


def runLang(que):
    print "start"
    myDict=dict()
    for i in xrange(10000):
        myDict[i]=i
    que.put(myDict)
    print "finish"


def run(fileToAnalyze):
    que=Queue()
    processList=[]
    dicList=[]
    langs= ["chi","eng"]
    for lang in langs:
        p=Process(target=runLang,args=(que,))
        processList.append(p)
        p.start()

    for p1 in processList:
        p1.join()

    print "here"

    for _ in xrange(len(langs)):
        item=que.get()
        print item
        dicList.append(item)

if __name__=="__main__":
    processList = []
    for fileToAnalyse in ["abc.txt","def.txt"]:
        p=Process(target=run,args=(fileToAnalyse,))
        processList.append(p)
        p.start()
    for p1 in processList:
        p1.join()
4

1 回答 1

16

这是因为当您将put大量项目放入 amultiprocessing.Queue时,一旦底层Pipe已满,它们最终会缓冲在内存中。缓冲区不会被刷新,直到有东西从 的另一端开始读取Queue,这将允许Pipe接受更多的数据。在其所有实例的缓冲区完全刷新到它们的底层之前, AProcess无法终止。这意味着如果您尝试一个进程而没有另一个进程/线程调用它,您可能会死锁。这在文档中提到QueuePipejoingetQueue

警告

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

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

请注意,使用管理器创建的队列不存在此问题。

您可以通过在清空父项join后才调用来解决此问题:Queue

for _ in xrange(len(langs)):
    item = que.get()
    print(item)
    dicList.append(item)

# join after emptying the queue.
for p in processList:
    p.join()

print("here")
于 2014-11-04T15:30:47.273 回答