生產者-消費者問題詳解
2009-11-30 22:07:03
分類:
要理解生產消費者問題,首先應弄清
pv操作的含義:pv
操作是由
p操作原語和
v操作原語組成(原語是不可中斷的過程),對訊號量進行操作,具體定義如下:
p(s):①將訊號量
s的值減1,即
s=s-1;
②如果s³0
,則該程序繼續執行;否則該程序置為等待狀態,排入等待佇列。
v(s):①將訊號量
s的值加1,即
s=s+1;
②如果s>0
,則該程序繼續執行;否則釋放佇列中第乙個等待訊號量的程序。
這只是書本的定義,對於這部分內容,老師先不要急於解釋上面的程式流程,而是應該讓學生首先知道
p操作與
v操作到底有什麼作用。
p操作相當於申請資源,而
v操作相當於釋放資源。所以要學生記住以下幾個關鍵字:
p操作-----
à申請資源
v操作----
à釋放資源
為此舉兩個生活中的例子:
例一:在公共**廳打**
公共**廳裡有多個**,如某人要打**,首先要進行申請,看是否有**空閒,若有,則可以使用**,如果**亭裡所有**都有人正在使用,那後來的人只有排隊等候。當某人用完**後,則有空**騰出,正在排隊的第乙個人就可以使用**。這就相當於
pv操作:
某人要打**,首先要進行申請,相當於執行一次
p操作,申請乙個可用資源(**);
某人用完**,則有空**騰出,相當於執行一次
v操作,釋放乙個可用資源(**)。
在多**課件中,這部分內容充分通過動畫效果,演示整個申請**資源(
p操作)與釋放**資源(
v操作)的過程,同時顯示當前可用的資源個數(**個數)。課件直觀生動,一目了然,學生非常容易接受,並且理解深刻。
在理解了
pv操作的的含義後,就必須講解利用
pv操作可以實現程序的兩種情況:互斥和同步。根據互斥和同步不同的特點,就有利用pv
操作實現互斥與同步相對固定的結構模式。這裡就不詳細講解了。但生產者
-消費者問題是乙個有代表性的程序同步問題,要學生透徹理解並不容易。但是如果我們將問題細分成三種情況進行講解,理解難度將大大降低。
1
)乙個生產者,乙個消費者,公用乙個緩衝區。
可以作以下比喻:將乙個生產者比喻為乙個生產廠家,如伊利牛奶廠家,而乙個消費者,比喻是學生小明,而乙個緩衝區則比喻成一間好又多。第一種情況,可以理解成伊利牛奶生產廠家生產一盒牛奶,把它放在好又多一分店進行銷售,而小明則可以從那裡買到這盒牛奶。只有當廠家把牛奶放在商店裡面後,小明才可以從商店裡買到牛奶。所以很明顯這是最簡單的同步問題。
解題如下:
定義兩個同步訊號量:
empty
——表示緩衝區是否為空,初值為1。
full
——表示緩衝區中是否為滿,初值為0。
生產者程序
while(true)
消費者程序
while(true)
消費者程序
while(true)
3
)一組生產者,一組消費者,公用
n個環形緩衝區
第三種情況,可以理解成有多間牛奶生產廠家,如蒙牛,達能,光明等,消費者也不只小明一人,有許許多多消費者。不同的牛奶生產廠家生產的商品可以放在不同的好又多分店中銷售,而不同的消費者可以去不同的分店中購買。當某一分店已放滿某個廠家的商品時,下乙個廠家只能把商品放在下一間分店。所以在這種情況中,生產者與消費者存在同步關係,而且各個生產者之間、各個消費者之間存在互斥關係,
他們必須互斥地訪問緩衝區。
解題如下:
定義四個訊號量:
empty
——表示緩衝區是否為空,初值為n。
full
——表示緩衝區中是否為滿,初值為0。
mutex1
——生產者之間的互斥訊號量,初值為1。
mutex2
——消費者之間的互斥訊號量,初值為1。
設緩衝區的編號為1~
n-1,定義兩個指標in和
out,分別是生產者程序和消費者程序使用的指標,指向下乙個可用的緩衝區。
生產者程序
while(true)
消費者程序
while(true); // 緩衝初始化為0, 開始時沒有產品
sem_t empty_sem; // 同步訊號量, 當滿了時阻止生產者放產品
sem_t full_sem; // 同步訊號量, 當沒產品時阻止消費者消費
pthread_mutex_t mutex; // 互斥訊號量, 一次只有乙個執行緒訪問緩衝
int product_id = 0; //生產者id
int prochase_id = 0; //消費者id
/* 列印緩衝情況 */
void print()
/* 生產者方法 */
void *product()
}/* 消費者方法 */
void *prochase()}
int main()
//初始化互斥訊號量
int ini3 = pthread_mutex_init(&mutex, null);
if(ini3 != 0)
// 建立n個生產者執行緒
ret= pthread_create(&id1, null, product, (void *)(&i));
if(ret != 0)
//建立n個消費者執行緒
ret= pthread_create(&id2, null, prochase, null);
if(ret != 0)
//銷毀執行緒
pthread_join(id1,null);
pthread_join(id2,null);
exit(0); }
生產者消費者 生產者與消費者模式
一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...
生產者消費者
using system using system.collections.generic using system.threading namespace gmservice foreach thread thread in producers q.exit console.read public...
生產者消費者
執行緒通訊 乙個執行緒完成了自己的任務時,要通知另外乙個執行緒去完成另外乙個任務.wait 等待 如果執行緒執行了wait方法,那麼該執行緒會進入等待的狀態,等待狀態下的執行緒必須要被其他執行緒呼叫notify方法才能喚醒。notify 喚醒 喚醒執行緒池等待執行緒其中的乙個。notifyall 喚...