計算機作業系統-訊號量經典問題
阿新 • • 發佈:2020-12-19
技術標籤:計算機作業系統
生產者-消費者(合作關係)
不能生產者在生產的時候 消費者進行消費 反之也不行
如果倉庫堆滿了 生產者不能再進行生產
如果倉庫空了 消費者不能再進行消費
記錄型訊號量寫法
semaphore mutex=1;//實現互斥
semaphore empty=n;//空緩衝的數量
semaphore full=0;//滿緩衝的數量
void producer(){
生產一個產品
P(empty); //判斷是否有消費者在消費 判斷empty>0嘛
P(mutex);
把產品放入緩衝區
V(mutex);
V(full);
}
void customer(){
P(full);
P(mutex);
從緩衝區中取出產品
V(mutex);
V(empty);
使用產品
}
AND型訊號量寫法
semaphore mutex=1;//實現互斥
semaphore empty=n;//空緩衝的數量
semaphore full=0;//滿緩衝的數量
void producer(){
生產一個產品
Swait(empty,mutex)
把產品放入緩衝區
Ssignal(mutex,full)
}
void customer(){
Swait(full,mutex) ;
從緩衝區中取出產品
Ssignal(mutex,empty)
使用產品
管程寫法
//N是公用緩衝池中具有N個緩衝區
Monitor Producerconsumer
{
/*變數說明*/ //成員變數
item buffer[N];
int in,out;//共享資料說明
condition notfull,notempty;//條件變數說明 //判斷資源是否滿或者空
int count; //緩衝池中已有的產品數目
public: //能被程序呼叫的過程
/*對資料結構操作的過程*/ //成員函式
void put(item x)
{
if(count >= N)cwait (notfull);//如果緩衝池已滿 該生產者程序需要掛起等待 並將該程序放進notfull阻塞佇列中
//cwait(notfull)應該等價於notfull.wait()
buffer[in] = x;
in = (in+1)%N;
count++;
csignal(notempty);//此時count增加了 公共資料發生了改變(也就是這裡不再是空的了 那些因為倉庫空而被掛起無法消費的消費者程序重新啟動) 重新啟動一個被掛起的程序 這裡面填notempty是因為要重啟的是放在notempty阻塞佇列裡面的程序
}
void get(item x)
{
if(count <= 0)cwait(notempty);
x = buffer[out];
out = (out+1)%N;
count--;
csignal(notfull);
}
{in = 0;out = 0;count = 0;} //這裡就是初始化資料
}PC;
void produce()//這個是一個程序
{
item x;
while(TRUE)
{
...
procdece an item in nextp;
PC.put(x); //直接呼叫PC管程
}
}
void consumer()
{
item x;
while(TRUE)
{
PC.get(x);
consume the item in nextx;
...
}
}
void main()
{
cobegin
producer();consumer();
coend
}
哲學家進餐問題(程序需要多個資源)
五個哲學家圍坐在一張圓桌上 每個哲學家面前一個碗一隻筷子 只有拿到兩隻筷子時才能進餐 進餐結束放下筷子
問題:如果讓併發執行可能大家都只拿到一支筷子而死鎖
解決辦法:
1.最多隻允許四個哲學家去拿筷子 這樣一定會有人可以拿到兩支筷子 然後釋放資源
2.(AND型)僅當哲學家能拿到左右兩支筷子時才能去拿筷子 要不然不能拿
3.讓奇數號的哲學家先拿左邊的筷子 再拿右邊的筷子 讓偶數號的哲學家先拿右邊的筷子 再拿左邊的筷子 (就是最開始相鄰的兩個人都競爭同一支筷子只有競爭拿到筷子的人才能拿另一隻 否則就等待)
AND型訊號量寫法
semaphone chopstick[5] = {1,1,1,1,1};
do
{
...
Swait(chopstick[i+1%5],chopstick[i]);//[i+1%5]就是另一隻筷子 並且數量不能超過5
.。。
SSignal(chopstick[i+1%5],chopstick[i]);
}while(TRUE);
讀者-寫者問題
允許同時多個讀者讀一本書 但是隻允許一個寫者寫書 並且在讀者和寫者不能同時讀寫一本書
記錄型訊號量
semaphore wmutex = 1;
semaphore rmutex = 1;//rmutex是防止多個程序同時對readcount進行更改 引起混亂 比如如果沒有wait(rmutex)和signal(rmutex)則假設有兩個讀者R1,R2 其中一個已經在讀書 另一個剛來 執行順序如下
/*
R1從readcount--開始 R2從if(readcount == 0)開始
此時 readcount = 1 wmutex = 0(因為R1進來時執行過wait(wmutex);)
R1 readcout-- //readcout = 0
R2 if(readcount == 0) //通過
R2 wait(wmutex) //wmutex = -1
R2 readcount++ //readcount = 1
R1 if(readcount == 0)//不通過
。。。
直到R2 signal(wmutex) //wmutex = 0
此時就出現了問題 因為此時沒有讀者在讀書 但是wmutex = 0(應該是1的) 寫者也進不去
*/
int readcount = 0;
void reader()
{
do{
wait(rmutex);//防止多讀者readcount寫入
if(readcount == 0)wait(wmutex);//如果在該讀者來之前沒人在讀書 則讓wmutex為0 不讓寫者通過
readcount++;//讀者數量+1
signal(rmutex);//寫入完畢 其他讀者可以寫入readcount
...
perform read operation;
...
wait(rmutex);//同樣效果 要對readcout寫入
readcount--;//讀者離開 數量-1
if(readcount == 0)signal(wmutex);//如果該讀者是最後一個讀者 則該讀者離開之後 就沒有人讀書了 那麼寫者可以通過 讓wmutex = 1
signal(rmutex);
}while(TRUE);
}
void Writer()
{
do
{
wait(wmutex);//判斷是否有讀者在內 沒有則可以通過
perform weite operation;
signal(wmutex);
}while(TRUE);
}
void main()
{
cobegin
Reader();Writer();
coend
}