#原創,轉載請聯系
我們都知道,主進程和子進程之間不能共享全局變量。那么他們之間怎么實現通信呢?
這就需要用到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(),運行多幾次,你會知道為什么的。