經典同步互斥問題
文章目錄
生產者消費者問題
生產者消費者應當是最最基本的同步互斥問題了。生產者生產了之後消費者才消費,消費者消費之後,通知生產者再去生產,而生產者和消費者互斥的訪問緩衝區。不難看出我們要設定的一個互斥變數mutex=1,empty=n,full=0;
具體問題描述如下:
該問題描述如下:有一個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能併發執行,在兩者之間設定一個具有多個緩衝區的緩衝池,生產者將它生產的產品放入一個緩衝區中,消費者可以從緩衝區中取走產品進行消費,顯然生產者和消費者之間必須保持同步,即不允許消費者到一個空的緩衝區中取產品,也不允許生產者向一個已經放入產品的緩衝區中再次投放產品。
mutex=1,empty=n,full=0;
Pp:生產者
Pp(empty)
Pp(mutex)
produce
Pp(mutex)
V(full)
Pc:消費者
P(full)
P(mutex)
consume
P(mutex)
V(empty)
哲學家就餐問題
哲學家就餐問題的三種解決方式:
1.互斥吃飯的動作
2.僅允許部分人(四個人)去搶筷子
3.按照一定規則去搶筷子(奇數編號的的哲學家先拿左邊的筷子,再拿右邊筷子,偶數編號則相反)
第一種:互斥吃飯的動作
mutex=1 P(mutex) get the right chopsticks get the left chopsticks eating P(mutex)
這樣的缺點就是資源利用不充分;
下面見第二種:僅允許部分人(四個人)去搶筷子
Pi
chopsticks[5]=[1,1,1,1,1] ,count=4
P(count)
P(chopsticks[i])
P(chopsticks[i+1])
eating
V(chopsticks[i])
V(chopsticks[i])
V(count)
另外一種解決方案就是,按照一定規則去搶筷子
chopsticks[5]=[1,1,1,1,1] if(i%2==0){ //判斷哲學家的編號的奇偶 p(chopsticks[i]) p(chopsticks[i+1]) eating V(chopsticks[i]) V(chopsticks[i+1]) thinking } else { p(chopsticks[i+1]) p(chopsticks[i]) eating V(chopsticks[i+1]) V(chopsticks[i]) thinking }
讀者與寫者問題
這個問題又可以分為三個個小問題,讀者優先,寫者優先和公平競爭。我們一個一個來看,先看讀者優先。
讀者優先
Reader process
mutex=1,count=0,mc=1;
P(mc)
V(mc)
if(count==1){
V(mutex)
}
reading
P(mc)
count--;
V(mc)
if(count==0){
V(mutex)
}
writer process
P(mutex)
writing;
V(mutex)
寫者優先
讀寫公平
wmutex=1;
mutex=1;
cmutex=1;
int count=0; //讀者個數
Reader
p(wmutex) //判斷是否有寫者進入
p(cmutex)
if(count==0){
p(mutex)
}
count++;
v(cmutex)
reading
v(wmutex)
p(cmutex)
count--
if(count==0){
v(mutex)
}
v(cmutex)
writer
p(wmutex)
p(mutex)
writing
v(mutex)
v(wmutex)
吃水果問題
問題描述:
吃水果問題:桌子有一隻盤子,只允許放一個水果,父親專向盤子放蘋果,母親專向盤子放桔子 兒子專等吃盤子的桔子,女兒專等吃盤子的蘋果。只要盤子為空,父親或母親就可以向盤子放水果, 僅當盤子有自己需要的水果時,兒子和女兒可從盤子取出。
問題分析:一個互斥的資源,盤子。兩個同步的關係,父親放好了蘋果通知女兒,女兒拿蘋果通知父母有了空盤子。母親這是放好了桔子通知兒子,兒子拿走了桔子去通知父母有了空盤子;需要一個訊號量互斥盤子是否可用,兩個同步訊號量;
mutex =1,apple=0,orange=0;
Father
p(mutex)
put a orange; //父親放橘子
v(orange)
Daughter
p(orange)
get a orange; //女兒拿橘子
v(mutex)
Mother
p(mutex)
put a apple; //母親放蘋果
v(apple)
Son
p(apple)
get a apple; //兒子放蘋果
v(mutex)
理髮師問題
問題描述:
假設有一個理髮店只有一個理髮師,一張理髮時坐的沙發,若干張普通椅子顧客供等候時坐。沒有顧客時,理髮師就坐在理髮的椅子上睡覺。顧客一到,他不是叫醒理髮師,就是離開。如果理髮師沒有睡覺,而在為別人理髮,他就會坐下來等候。如果所有的椅子都坐滿了人,最後來的顧客就會離開。
問題分析:可以把沙發,座椅,顧客用同一個訊號量表示
mutex=1;
ready=0;
chair=n+1;沙發和座椅總共的個數
finsh=1;//理髮師初始位置空閒
customer
p(mutex)
if(chair>0){
chair--;
v(mutex)
v(ready)
p(finsh) //進入等待理髮的佇列
}
else{
v(mutex)
}
barber
p(ready)
hair-cut
p(mutex)
chair++;
v(mutex)
v(finsh)
吸菸者問題
抽菸者問題。假設一個系統中有三個抽菸者程序,每個抽菸者不斷地捲菸並抽菸。抽菸者捲起並抽掉一顆煙需要有三種材料:菸草、紙和膠水。一個抽菸者有菸草,一個有紙,另一個有膠水。系統中還有兩個供應者程序,它們無限地供應所有三種材料,但每次僅輪流提供三種材料中的兩種。得到缺失的兩種材料的抽菸者在捲起並抽掉一顆煙後會發訊號通知供應者,讓它繼續提供另外的兩種材料。
ps=1;
pa=0; //通知有菸草的人
pb=0; //通知有紙的人
pc=0; //同志有膠水的人
supplier
p(ps)
num=random%3;
if(num==0){
v(pa)
}
else if(num==1){
v(pb)
}
else {
v(pc)
}
process a
p(pa)
get paper and glue
smoking
v(ps)
process b
p(pb)
get tobacco and glue
smoking
v(ps)
process c
p(pc)
get tobacco and paper
smoking
v(ps)
猴子過橋問題
問題概述:
在兩個相對的懸崖間,有一根繩子。懸崖兩邊有許多猴子,分別要到對面去。其中有一些屬性,比如不能讓不同方向的猴子同時處於繩上,同一方向的猴子必須依次通過等等。假設繩子兩端的方向是南北。問,如何使用同步原語解決這個問題?
mutex=1; 用來互斥橋的使用
int count1=0; 計算繩子上猴子個數(從南到北)
int count2=0; 計算繩子上猴子個數(從北到南)
c1mutex=1; 用來互斥count1修改
c2mutex=1; 用來互斥count1修改
從南到北
p(c1mutex)
count1++ // 統計從南到北方向上猴子的個數
v(c1mutex)
if(count1==1){ //若為第一個猴子則去爭奪,橋的使用權
p(mutex)
}
jump off the bridge
p(c1mutex)
count1--
v(c1mutex)
if(count1==0){ //若為最後一個猴子,則釋放出橋的使用權
v(mutex)
}
從北到南
p(c2mutex)
count2++
v(c2mutex)
if(count2==1){
p(mutex)
}
jump off the bridge
p(c2mutex)
count2--
v(c2mutex)
if(count2==0){
v(mutex)
}
麵包師問題
參考資料:2019年王道作業系統
下載地址:2019年王道作業系統