1. 程式人生 > >經典程序同步與互斥問題——生產者消費者問題

經典程序同步與互斥問題——生產者消費者問題

問題描述:生產者——消費者問題是指有兩組程序共享一個環形的緩衝池,一組稱為生產者,一組稱為消費者。緩衝池是由若干個大小相等的緩衝區組成,每個緩衝區可以容納一個產品。生產者程序不斷的將產品放入緩衝池中,消費者不斷將產品從緩衝池中取出。

核心:生產者——消費者問題,既存在著程序同步問題,也存在著臨界區互斥問題。當緩衝區滿時,表示供大於求,生產者必須停止生產,進入等待狀態,同時喚醒消費者;當所有緩衝區都為空時,表示供不應求,消費者必須停止消費,喚醒生產者。這就是生產者程序和消費者程序的同步關係。對於緩衝池,生產者和消費者都要使用它,顯然他是一個臨界資源,對於緩衝池的操作必須是互斥的。

這裡採用P、V操作解決生產者消費者問題的形式化描述

semaphore mutex=1;
semaohore empty=n;
semaphore full=0   //定義是3個訊號量
int i,j;
ITEM buffer[n];
ITEM data_p,data_c;
void producer()
{
while(true)
{
produce an item in data_p;
P(empty);
P(mutex);
buffer[i]=data_p;
i=(i+1)%n;
V(mutex);
V(full);
}
}

void consumer()
{
while(true)
{
P(full);
P(mutex);
data_c=buffer[j];
j=(j+1)%n;
V(mutex);
V(empty);
consume the item in data_c;
}
}

總結:

1.把共享緩衝池的n個緩衝區視為臨界資源,程序在使用時,首先要檢查是否有其他程序在臨界區,確認沒有時在進入。在程式中,P(mutex)和V(mutex)用於實現對臨界區的互斥,P(mutex)和V(mutex)必須成對出現。

2.訊號量full表示有資料的緩衝區的數目,初始值為0,empty表示空閒緩衝區的數目,初始值為n。他們表示的都是資源的數目,因此稱為資源訊號量。實際上,full和empty之間存在關係,full+empty=n。對資源訊號量的PV操作同樣需要成對出現,與互斥訊號量不同的是,P操作和V操作分別處於不同的程式中,例如P(empty)在生產者程序中,而V(empty)在消費者程序中。當生產者程序因執行P(empty)而阻塞時,由消費者程序的V(empty)將其喚醒;同理,當消費者程序因執行P(full)而阻塞時,生產者程序用V(full)將其喚醒。

思考:在生產者進行中的P(empty)和P(mutex)的位置能否互換?

顯然是不能的,如果交換後,就可能會發生死鎖。可以想象這種情況,生產者程序,執行P(mutex)進入臨界區,接下來執行P(empty),但現在empty為0,生產者被阻塞無法繼續生產,用時它又已經進入了臨界區,消費者進行由於無法進入臨界區,也被阻塞。這樣整個系統都被阻塞,發生死鎖現象。