Python中多執行緒的阻塞問題

2021-08-03 12:14:44 字數 2542 閱讀 8710

在使用queue模組+多執行緒模擬生產者+消費者問題時,遇到了乙個小問題,現在記錄下來。供可能會遇到類似問題的初學者們參考。

該問題的完整參考**如下。主要實現了以下的功能:在乙個執行緒中,開啟生產者模式,生成出來的object會put進乙個queue物件queue中。除此以外,在n個執行緒中(本**中n為5,nfuncs = 5),開啟消費者模式,每乙個消費者執行緒會在乙個while迴圈中不斷地從queue中消耗乙個object(使用get方法),直到生產者生產出的object被全部消耗(本**中設為100個object)。

from random import randint

from time import sleep

from queue import queue

from threading import thread,lock,currentthread

lock = lock()

def writes(queue):

print "producing object for q...",

queue.put('***', 1)

print "size now", queue.qsize()

def readq(queue):

val = queue.get(1)

print "consumed object from q... size now", \

queue.qsize()

print currentthread().name

def writer(queue, loops):

for i in range(loops):

lock.acquire()

writes(queue)

lock.release()

sleep(0.1)

def read(queue):

while queue.qsize() >0 :

sleep(randint(2, 4))

lock.acquire()

readq(queue)

lock.release()

funcs = [writer, read]

nfuncs = range(5)

def main():

nloops1 = 100

q = queue(1024)

thread =

t = thread(target = writer, args = (q, nloops1))

for i in nfuncs:

t = thread(target = read, args = (q,))

for i in range(len(thread)):

thread[i].start()

for i in range(len(thread)):

thread[i].join()

print "all done"

if __name__ == '__main__':

main()

為了防止生產速度跟不上消費的速度,生產線程中每次生產僅間隔0.1秒,且在消費執行緒中每次消費之前,隨機sleep 2~3秒。

在執行之後,生產的object數量達到100(實際不會print 100號object的生成,因為在生產的過程中已經開始消費),然後多個執行緒開始消費。然而在把object數量消費至0以後,執行緒們並不會結束,既「print 「」all done「」」語句一直沒有被執行。

思考以後,得出了三種解決途徑:

2.試圖考慮為什麼執行緒會阻塞。

發現在read函式中,如前所述,在每次消費之前,隨機sleep 2~3秒。於是可能會出現以下的問題。

當 queue.qsize() = 1的時候,某個執行緒x進入了while迴圈,然後開始睡眠2~3秒,在這個睡眠過程中,gui切換至其它的執行緒,此時由於執行緒x處於睡眠,並沒有呼叫readq函式,因此queue中仍然有乙個元素。以此類推,每個程序都在queue.qsize() = 1時進入了while迴圈,然後最早結束睡眠的執行緒將呼叫readq函式中的queue.get(1)。之後其它程序在呼叫queue.get(1)時,將會因為queue中缺少元素阻塞。

解決方法如下: 

def read(queue):

sleep(randint(2, 4))

while queue.qsize():

lock.acquire()

readq(queue)

lock.release()

sleep(randint(2, 4))

在while之前睡眠,且將每次消費時所需的睡眠放至readq函式之後。可避免多個執行緒同時進入while迴圈,該改進將不會

引起阻塞。

3.queue中的get方法,若將其引數設定為非0,則不會因為佇列中沒有可用元素而阻塞。將get的引數設定為0,

利用try/excep語句,

當get不到資料引起異常時,excep乙個break,中斷執行緒。

多執行緒 阻塞佇列

blockingqueue最終會有四種狀況,丟擲異常 返回特殊值 阻塞 超時,下表總結了這些方法 丟擲異常 特殊值阻塞 超時插入add e offer e put e offer e,time,unit 移除remove poll take poll time,unit 檢查element peek...

多執行緒 阻塞佇列

1 當佇列滿的時候,插入元素的執行緒被阻塞,直達佇列不滿。2 隊列為空的時候,獲取元素的執行緒被阻塞,直到佇列不空。生產者就是生產資料的執行緒,消費者就是消費資料的執行緒。在多執行緒開發中,如果生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理完,才能繼續生產資料。同樣的道理,...

python中多執行緒 Python之多執行緒

python之多執行緒 一 概念 1 多工可以由多程序完成,也可以由乙個程序內的多執行緒完成。程序是由若干的執行緒組成,乙個程序至少有乙個程序。執行緒是作業系統直接支援的執行單元,天賜高階預壓通常都是內建多執行緒的支援,python的執行緒是真正的posix thread而不是模擬出來的執行緒。2 ...