多執行緒中的生產者和消費者模式

2021-08-19 12:56:24 字數 3038 閱讀 8575

當乙個程序中存在多個執行緒時,且此時有可能對同一資源進行訪問,那麼此時可能會發生安全問題,因此在訪問之前需要將這些資源放在同步**塊中或同步方法中,通過synchronized關鍵字宣告,此時只能存在乙個執行緒並且該執行緒在獲取到對應的鎖後才能對共享資源操作,完成之後其他執行緒才能獲得該鎖進而操作共享資源。

這些是多執行緒在處理同一資料時的一些基本操作,那麼此時若有多個執行緒要對同一資源操作,但實現不同的功能。比如在火車站或地鐵站都會設有安檢,乘客的行李物品從一邊進,從另一邊出,而生產者和消費者模式就與其類似。

現在來分析一下,如果此時有一物品package要進安檢進行檢測然後要出來,所以要有兩種操作,建立乙個resource類,建立兩個方法乙個控制進入,乙個控制輸出。

class resource catch (interruptedexception e) 

this.name = name;

system.out.println(thread.currentthread().getname()+"-->in"+this.name);

flag =true;

this.notify();

}public

synchronized

void

out() catch (interruptedexception e)

}system.out.println(thread.currentthread().getname()+"-->out"+this.name);

flag = false;

this.notify();}}

那麼這裡的flag有什麼作用呢,首先要了解執行緒的等待喚醒機制,由於只有輸入乙個package才能輸出乙個,所以兩個執行緒應交替執行,但在有相同鎖的情況下,執行緒會搶cpu執行權,而這時會有不確定性,所以可能會出現與實際情況不符,因此要在乙個執行緒a執行時,應保證另一線程b處於等待狀態,a執行完畢後喚醒執行緒b然後處於等待,同理b也模仿這一行為,這就避免了邏輯錯誤的發生。然後看flag,在這裡如果令當前執行緒等待的條件與傳入的值不匹配時才進行方法中的操作,否則進入等待狀態,當正常操作完後喚醒另一線程,並將flag反轉,使得交替的工作正常進行。

下面是完整的程式:

可以看到輸入與輸出交替,這是兩個執行緒進行操作的效果,如果有更多的執行緒呢?

在主方法中再建立兩個執行緒

可以看到當有兩個以上執行緒執行時,會出現一進兩齣或多出的現象,這是什麼原因,可以分析一下,比如此時有四個執行緒a,b,c,d,a和b控制輸入,c和d控制輸出。在程式進行一段時間後如果flag為false,則由a和b中搶到執行權的乙個執行輸入操作,假設a執行了輸入,然後反轉flag再喚醒執行緒,此時因為滿足flag條件則a等待,而b,c,d都具有執行資格,又假設b搶到執行權,由於flag為真,b也等待。然後執行c,c執行了輸出操作,反轉flag,然後喚醒處於等待且時間最長的a,而c本身失去了執行資格,d也是如此,接下來a有執行一次輸入,然後喚醒的正是執行緒b,而b已經是等待狀態所以不必判斷直接執行輸入操作,這就導致了兩次輸入一次輸出的情況,當然繼續分析也會出現其他結果。

那麼如何解決這一問題?由於在某時刻某個執行緒可能被喚醒時省略了判斷的一步,從而發生安全問題,所以將if判斷改為while,此時的執行緒就會被判斷不止一次。

這下解決了輸入輸出不一致的邏輯問題,但是程式執行一會兒會自動停止,因為當c和d在等待時,執行緒a執行後在等待前喚醒了正在等待的b,但是在while迴圈裡會再次判斷,a會將flag反轉為不可執行狀態,而b恰好滿足,因此b又失去了執行資格,此時沒有執行緒執行,程式就會停止。所以解決的方法就是在每次執行緒執行完後喚醒所有正在等待的執行緒,即呼叫notifyall方法。

這下問題都解決了,達到了開頭所說的行李過安檢的效果,也是所謂的生產者消費者。

多執行緒 生產者和消費者

生產者 消費者問題 生產者向產品區里放產品,當產品區里滿了,需要等待 消費者從產品區里取產品消耗,當產品區里空了,需要等待。public class producerandconsumer 消費者 static class consumer implements runnable catch int...

多執行緒 生產者和消費者

前面說過,每個執行緒都有自己的資源,但是 區是共享的,即每個執行緒都可以執行相同的函式。這可能帶來的問題就是幾個執行緒同時執行乙個函式,導致資料的混亂,產生不可預料的結果,因此我們必須避免這種情況的發生。c 提供了乙個關鍵字lock,它可以把一段 定義為互斥段 critical section 互斥...

多執行緒 生產者消費者

這個就不多說了,直接上 include include using namespace std const unsigned short size of buffer 10 緩衝區長度 unsigned short productid 0 產品號 unsigned short consumeid 0...