【python】多線程queue導致的死鎖問題


寫了個多線程的python腳本,結果居然死鎖了。調試了一整天才找到原因,是我使用queue的錯誤導致的。

 

為了說明問題,下面是一個簡化版的代碼。注意,這個代碼是錯的,后面會說原因和解決辦法。

import Queue
import threading

queue = Queue.Queue()

def test(q):
    while True:
        if q.qsize() != 0:
            d = q.get()
            print d
        else:
            break

def 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 Queue
import threading

queue = 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() break

def 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()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM