问题引出:
未设置daemon标记的进程在主进程退出时不会自动退出;
子进程向Queue put(),在Queue清空前join,主进程退出时子进程不能退出;
问题1,参考stackoverflow上@dano的回答 ,粗浅翻译聊且一看:
threading 或 multiprocessing中的join() 方法与str的join()方法没关系,不像后者只是把一些东西连接起来,而是意味着“等待进程线程或进程结束”。使用join这个名称只是因为multiprocessing模块的API想要尽量向threading模块靠拢,而threading模块的Thread对象使用join方法。使用join来表述“等待一个线程结束”在许多语言中都是通用的,所以Python沿用了这种用法。
如你所述,在加入和未加入join()调用的情况下都出现了20秒的延迟,主进程退出时会隐式地对所有运行着的multiprocessing进程实例调用join()方法。这部分没有在multiprocessing的文档中清晰表述,但是在“编程指南”(Programming Guidelines)一节中有所提及。
注意:任何非守护进程都会自动地被join,可以在进程start前通过设置进程的daemon标志位为True来覆盖此设置。
Python
p = Process(target=say_hello)
p.daemon = True
p.start()
# Both parent and child will exit here, since the main process has completed.
1
2
3
4
p=Process(target=say_hello)
p.daemon=True
p.start()
# Both parent and child will exit here, since the main process has completed.
如果按上述设置,主进程退出后子进程将会立即终止。
进程的daemon标志是一个布尔值,需要在start()前设置。
初始值继承至父进程。
当进程退出时会尝试终止所有守护子进程。
问题2,参考multiprocessing的“编程指南”(Programming Guidelines):
join使用queue的子进程
请牢记以下事情:当一个进程向queue put项目时,在queue中所有缓冲的项目都被消费者取走并进行下一步处理之前,该进程会一直等待(子进程可以通过调用cancel_join_thread()方法来避免此种行为)。
这意味着在用queue之前,你必须确认queue里的所有项目都已经被处理,然后才能join这个进程,不然的话向queue put项目的进程可能不一定能够退出。还要注意,没有设置daemon标记的进程都是自动join的。
下面是一个死锁的例子:
An example which will deadlock
Python
from multiprocessing import Process, Queue
def f(q):
q.put('X' * 1000000)
if __name__ == '__main__':
queue = Queue()
p = Process(target=f, args=(queue,))
p.start()
p.join() # this deadlocks
obj = queue.get()
1
2
3
4
5
6
7
8
9
10
11
frommultiprocessingimportProcess,Queue
deff(q):
q.put('X'*1000000)
if__name__=='__main__':
queue=Queue()
p=Process(target=f,args=(queue,))
p.start()
p.join()# this deadlocks
obj=queue.get()
解决方法是互换最后两行的位置(或者只去掉p.join()一行)。
或者在f函数末尾加一行 q.cancel_join_thread()
最后编辑:2016-07-04作者:yong
这个作者貌似有点懒,什么都没有留下。