標籤:release put style get 死結 nbsp else 取得資料 python指令碼
寫了個多線程的python指令碼,結果居然死結了。調試了一整天才找到原因,是我使用queue的錯誤導致的。
為了說明問題,下面是一個簡化版的代碼。注意,這個代碼是錯的,後面會說原因和解決辦法。
import Queueimport threadingqueue = Queue.Queue()def test(q): while True: if q.qsize() != 0: d = q.get() print d else: breakdef main(): global queue n = 100 for i in range(66): queue.put(i) threads = [] for i in range(n) threads.append(threading.Thread(target=test, args = (queue,))) for i in range(n): threads[i].start() for i in range(n): threads[i].join()
上面這個代碼是會造成死結的。原因就在下面這一小段。
while True: if q.qsize() != 0: d = q.get()
由於有多個線程同時運行此段代碼,所以隊列q是各個線程共用的。
如果在q只剩一個資料的時候,有3個線程都運行到if q.qsize() != 0:,那麼這3個線程都會滿足此條件。從而繼續運行。
然後,在d = q.get()處,只有一個線程能夠取到資料,此後隊列為空白,另外兩個線程無法取得資料,從而鎖死在此處。
解決方案:加鎖
import Queueimport threadingqueue = Queue.Queue()mutex = threading.Lock()def test(q): global mutex while True: mutex.acquire() if q.qsize() != 0: d = q.get() mutex.release() print d else: mutex.release() breakdef main(): global queue n = 100 for i in range(66): queue.put(i) threads = [] for i in range(n) threads.append(threading.Thread(target=test, args = (queue,))) for i in range(n): threads[i].start() for i in range(n): threads[i].join()
【python】多線程queue導致的死結問題