併發的程序常常會用到隊列,用於進程/線程間的通訊。python
Python 中用於進程間通訊和線程間通訊的隊列的接口是同樣的,可是實現和效率倒是不一樣的,一個最大的區別在於:進程間的隊列在入隊時會對數據進行序列化,而線程間的隊列則不會序列化數據,這致使兩者效率上會有明顯的區別。這一點,文檔上沒有明確說明,可是能夠本身經過實驗來證明。併發
import queue from threading import Thread from multiprocessing import Queue, Process import time th_q = queue.Queue() proc_q = Queue() def th_worker(q): time.sleep(5) x = q.get() print('msg from thread queue: ' + str(x)) def proc_worker(q): time.sleep(5) x = q.get() print('msg from proc queue: ' + str(x)) th = Thread(target=th_worker, args=(th_q,)) th.start() p = Process(target=proc_worker, args=(proc_q,)) p.start() d = {'a':1, 'b':2} th_q.put(d) proc_q.put(d) time.sleep(1) d['a'] = 0 d['b'] = 5
運行上面的程序,結果是:線程
msg from thread queue: {'b': 5, 'a': 0}
msg from proc queue: {'b': 2, 'a': 1}
能夠看出,線程間的隊列上保存的是對象的引用,而非序列化的數據,而進程間的隊列保存的是序列化的數據,因此不會隨着原有對象的改變而改變。對象
注意d['a'] = 0 前一行的 time.sleep(1), 這一行對於驗證兩種隊列的區別很是重要,若是沒有這一行,結果就是這樣的:blog
msg from thread queue: {'b': 5, 'a': 0}
msg from proc queue: {'b': 5, 'a': 0}
這是由於輸入到隊列的 item 的序列化動做是在一個隊列內部的線程中進行的,不會佔用使用隊列的用戶線程的計算時間。(這個隊列內部的線程,multiprocess 模塊的文檔中略有說明:When a process first puts an item on the queue a feeder thread is started which transfers objects from a buffer into the pipe.)接口