Linux元件封裝(五)乙個生產者消費者問題示例

2022-05-23 04:33:10 字數 2097 閱讀 4424

生產者消費者問題是計算機中一類重要的模型,主要描述的是:生產者往緩衝區中放入產品、消費者取走產品。生產者和消費者指的可以是執行緒也可以是程序。

生產者消費者問題的難點在於:

為了緩衝區資料的安全性,一次只允許乙個執行緒進入緩衝區,它就是所謂的臨界資源。

生產者往緩衝區放物品時,如果緩衝區已滿,那麼需要等待,一直到消費者取走產品為止。

消費者取走產品時,如果沒有物品,需要等待,一直到有生產者放入為止。

第乙個問題屬於互斥問題,我們需要使用一把互斥鎖,來實現對緩衝區的安全訪問。

後兩個屬於同步問題,兩類執行緒相互協作,需要兩個條件變數,乙個用於通知生產者放入產品,乙個用來通知消費者取走物品。

生產者執行緒的大概流程是:

1.加鎖

2.如果緩衝區已滿,則等待。

3.放入物品

4.解鎖

5.通知消費者,可以取走產品

消費者的邏輯恰好相反:

1.加鎖

2.緩衝區為空,等待

3.取走物品

4.解鎖

5.通知生產者,可以放入物品

我們設計出乙個緩衝區:

#ifndef buffer_h_

#define buffer_h_#include

"noncopyable.h

"#include

"mutexlock.h

"#include

"condition.h

"#include

class

buffer : noncopyable

;#endif

//buffer_h_

這裡注意,我們把同步與互斥的操作都放入buffer中,使得生產者和消費者執行緒不必考慮其中細節,這符號軟體設計的「高內聚、低耦合」原則。

還有一點,mutex被宣告為mutable型別,意味著mutex在const函式中仍然可以被改變,這是符合程式的邏輯的。把mutex宣告為mutable,是一種標準實踐。

重點是push和pop的實現:

void buffer::push(int

val)

full_.notify();

}int

buffer::pop()

empty_.notify();

return

temp;

}

這裡注意:

1.條件變數的等待必須使用while,這是一種最佳實踐,原因可見condition的封裝linux元件封裝(二)中條件變數condition的封裝。

2.可以先notify再解鎖,也可以先解鎖。不過推薦先解鎖,原因是如果先notify,喚醒乙個執行緒b,但是還未解鎖,此時如果執行緒切換至剛喚醒的執行緒b,b馬上嘗試lock,但是肯定失敗,然後阻塞,這增加了一次執行緒切換的開銷

我們還可以繼續封裝,將緩衝區與多個生產者、消費者封裝成乙個車間類,如下:

#ifndef workshop_h_

#define workshop_h_#include

"noncopyable.h

"#include

"buffer.h

"#include

class

producerthread;

class

consumerthread;

class

workshop : noncopyable

;#endif

//workshop_h_

這樣就可以方便的指定執行緒的數目。

完整的專案**請參見這裡:生產者消費者完整**

linux執行緒 生產者 消費者

cpp view plain copy include include define buffer size 16 緩衝區數量 struct prodcons 初始化緩衝區結構 void init struct prodcons b 將產品放入緩衝區,這裡是存入乙個整數 void put struc...

Linux 生產者消費者模型

生產者消費者模型 為什麼要使用生產者消費者模型?生產者消費者模型遵循 基於生產者消費者模型的阻塞佇列 include include include include include include using namespace std class blockqueue void unlockque...

Linux多執行緒 生產者消費者

生產者消費者問題 這是乙個非常經典的多執行緒題目,題目大意如下 有乙個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能併發執行,在兩者之間設定乙個有多個緩衝區的緩衝池,生產者將它生產的產品放入乙個緩衝區中,消費者可以從緩衝區中取走產品進行消費,所有生產者和消費者都是非同步...