主进程与子进程之间的通信

#原创,转载请联系

我们都知道,主进程和子进程之间不能共享全局变量。那么他们之间怎么实现通信呢?

这就需要用到Queue(队列)了。

1.队列的简单介绍:

队列是常见的数据结构,采用先进先出的原则。从队列的尾部存数据,从队列的头部取数据。

2.怎么创建一个队列:

q = multiprocessing.Queue()

括号里面可以传进去一个参数,表示队列的长度。

3.队列会出现的BUG?

import multiprocessing
import time

q = multiprocessing.Queue(3)
q.put("1")
q.put("2")
q.put("3")
print("队列是否为满?",q.full())
print("队列是否为空?",q.empty())

输出:
队列是否为满? True
队列是否为空? True(False)

注意输出的地方。运行多几次,输出结果会不同。有时候队列是否为空是True,有时候队列是否为False。出现True是什么原因呢?

我已经把3个东西放进队列了啊,为什么还会显示队伍为空是对的呢?原因就是,put函数还没来的及把数据放进队列里,你就打印了出来了。

然后你就会问,为什么,还没把数据放进队列里,就会显示队伍是否为满是对的呢?

原因就是,这是Queue内部的一个机制。

内部的机制应该是这样子的,举个例子,有两个教室,两个教室都分别有一个指挥官。第一个教室的指挥官叫3个同学去第二个教室,然后他就记在本子上了,有3个同学已经去了第二个教室,对应的是,队列已经满了,打印输出,队列是否为满是真的。

但是这3个学生还没走到第二个教室,第二个教室的指挥官就在本子上写,没有人来,对应的是,队列是空的,打印输出,队列是否是空的是真的。

但是学生如果走得快点,第二个教室的指挥官在本子上写,哎呀,有3个学生来了,对应的是,队列是满的,打印输出,队列是否是空的是假的。

4.队列的阻塞问题

如果一个队列最大的长度是3个,你put进去了4个。那么最后一个put的很理所当然的要等待。

但是,

最后一个等待的时候,会阻塞,使下面的代码不能运行。

import multiprocessing
import time

q = multiprocessing.Queue(3)
q.put("1")
q.put("2")
q.put("3")
q.put("4")
print("队列是否为满?",q.full())
print("队列是否为空?",q.empty())

输出:
(输出为空,但是程序并没有结束)

上述代码中,队列的最大长度是3,放进了3个后,正想放第4个,但是放不下了。那么第4个就只有在这里等待。但是他不仅要等待,还是阻塞状态。只有等他运行了,他下面的代码才能继续运行。

还有另一种情况:

不仅仅是没地方放的时候会造成阻塞,如果队列为空,你要在里面拿东西,也会造成阻塞。

import multiprocessing

q = multiprocessing.Queue(3)
q.get()
print("走开")
print("我要吃汉堡包")

输出:
(内容为空,且进程没有结束)

5.进程之间的通信

说了这么多,该开始讲一下进程之间怎么实现通信的了。

实现目标:我们在主进程中创建两个子进程,一个用来把数据放在队列里,一个用来在队列里取数据,这样一来就实现了通信的功能了吧。

import multiprocessing
import time


def put_data(queue):
    for i in "abcde":
        queue.put(i)
        time.sleep(0.5)
        print("把数据%s放在队列里:" % i)

def get_data(queue):
    while not queue.empty():
        time.sleep(0.5)
        data = queue.get()
        print("从队列拿到数据:%s" % data)

if __name__ == '__main__':
    queue = multiprocessing.Queue(5)
    p1 = multiprocessing.Process(target=put_data,args=(queue,))
    p1.start()
    p1.join()  
    p2 = multiprocessing.Process(target=get_data, args=(queue,))
    p2.start()
    p2.join()  # 如果不加上p1.join和p2.join会发生很奇怪的BUG,get_data函数的里面的queue.empty会出现BUG,原理就是第3.所说的。
会导致p2线程误判为空,还没取完数据就结束任务了。


输出:
把数据a放在队列里:
把数据b放在队列里:
把数据c放在队列里:
把数据d放在队列里:
把数据e放在队列里:
从队列拿到数据:a
从队列拿到数据:b
从队列拿到数据:c
从队列拿到数据:d
从队列拿到数据:e

注意红色字的说明!去掉p1.join()和p2.join(),运行多几次,你会知道为什么的。

原文地址:https://www.cnblogs.com/chichung/p/9533227.html