生產者消費者問題是計算機中一類重要的模型,主要描述的是:生產者往緩衝區中放入產品、消費者取走產品。生產者和消費者指的可以是執行緒也可以是程序。
生產者消費者問題的難點在於:
為了緩衝區資料的安全性,一次只允許乙個執行緒進入緩衝區,它就是所謂的臨界資源。
生產者往緩衝區放物品時,如果緩衝區已滿,那麼需要等待,一直到消費者取走產品為止。
消費者取走產品時,如果沒有物品,需要等待,一直到有生產者放入為止。第乙個問題屬於互斥問題,我們需要使用一把互斥鎖,來實現對緩衝區的安全訪問。
後兩個屬於同步問題,兩類執行緒相互協作,需要兩個條件變數,乙個用於通知生產者放入產品,乙個用來通知消費者取走物品。
生產者執行緒的大概流程是:
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(intval)
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多執行緒 生產者消費者
生產者消費者問題 這是乙個非常經典的多執行緒題目,題目大意如下 有乙個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能併發執行,在兩者之間設定乙個有多個緩衝區的緩衝池,生產者將它生產的產品放入乙個緩衝區中,消費者可以從緩衝區中取走產品進行消費,所有生產者和消費者都是非同步...