Python使用队列(multiprocess.Queu)进行多进程通信遇到的坑

问题:在使用multiprocessing.Queue进行多进程传递数据时,明明进程已经执行完毕,却在执行join()时发生不明阻塞。

代码:

from multiprocessing import Process, Queue, current_process


def main():
    plist = []
    queue = Queue()
    for i in range(8):
        plist.append(Process(target=run, args=(queue,)))

    for i in plist:
        i.start()
    for i in plist:
        # 在这里被阻塞
        print(i.name + "----join")
        i.join()

    while not queue.empty():
        print(queue.get())


def run(queue):
    # 64以及以下正常结束   65以及以上阻塞
    # 出问题数量似乎和put内容的大小有关
    for i in range(64):
        queue.put("123---")
    print(current_process().name + "--end")


if __name__ == "__main__":
    main()

正常运行结果:

Python使用队列(multiprocess.Queu)进行多进程通信遇到的坑_第1张图片

因不明原因,主进程在join()处被阻塞:

Python使用队列(multiprocess.Queu)进行多进程通信遇到的坑_第2张图片

原因:

    通过查阅文档发现:

    如果一个子进程将一些对象放进队列中 (并且它没有用JoinableQueue.cancel_join_thread 方法),那么这个进程在所有缓冲区的对象被刷新进管道之前,是不会终止的。(if a child process has put items on a queue (and it has not usedJoinableQueue.cancel_join_thread), then that process will not terminate until all buffered items have been flushed to the pipe.)

  这意味着,除非你确定所有放入队列中的对象都已经被消费了,否则如果你试图等待这个进程,你可能会陷入死锁中。相似地,如果该子进程不是后台进程,那么父进程可能在试图等待所有非后台进程退出时挂起。(This means that if you try joining that process you may get a deadlock unless you are sure that all items which have been put on the queue have been consumed. Similarly, if the child process is non-daemonic then the parent process may hang on exit when it tries to join all its non-daemonic children.)

注意用管理器创建的队列不存在这个问题。

因此,在使用Queue进行进程通信时,最好边put边get,防止死锁。

参考文档:https://docs.python.org/zh-cn/3/library/multiprocessing.html#multiprocessing.Process

你可能感兴趣的:(Python3,Python,死锁)