對(duì)于進(jìn)程這塊來說翩腐,同步問題算是一個(gè)大頭了,我也是看了好幾遍何什,真的服
王道里面這樣說:“如果一個(gè)操作想要取得資源你就在它前面P一下那個(gè)資源等龙,如果一個(gè)操作產(chǎn)生了一個(gè)資源后,你就要在它后面V一下”罐栈;
這個(gè)確實(shí)荠诬,
申請(qǐng)資源之前看看位仁,有沒有資源取得,有的話自然進(jìn)入下一步钧嘶,沒有的話琳疏,阻塞了摄欲;
生產(chǎn)了資源的胸墙,生產(chǎn)了之后V一下按咒,這個(gè)時(shí)候上面阻塞的那個(gè)P就可以繼續(xù)執(zhí)行下去了(這也是所謂的喚醒)励七;
幾個(gè)經(jīng)典的問題
- 生產(chǎn)者/消費(fèi)者
這里面就有兩個(gè)進(jìn)程,producer()吼野、consumer()两波;
一個(gè)產(chǎn)生資源,一個(gè)取資源单起,還有一個(gè)用來放資源的緩沖區(qū)n個(gè)空間劣坊;
semaphore mutex=1;
semaphore empty=n;
semaphore full=0;
producer(){
while(1){
p(empty);
p(mutex);
...produce
v(mutex);
v(full);
}
}
consumer(){
while(1){
p(full);
p(mutex);
...consume;
v(mutex);
v(empty);
}
}
這個(gè)里面為啥要用互斥呢局冰!mutex
因?yàn)閷?duì)緩沖區(qū)的訪問得互斥,同一時(shí)刻只可以有一個(gè)進(jìn)程對(duì)緩沖區(qū)操作碳胳;
同步嘛
因?yàn)槊看紊a(chǎn)總要看看緩沖區(qū)滿沒滿吧赠摇,緩沖區(qū)滿了就不能在放了(阻塞)藕帜,或者緩沖區(qū)是不是被取空了,空了也不能再取了(阻塞)贝攒;
- 多角色消費(fèi)者問題
生產(chǎn)者 父親/母親 消費(fèi)者 兒子/女兒
父親放蘋果/母親放橘子 兒子吃橘子/女兒吃蘋果
這里涉及到四個(gè)進(jìn)程时甚,父親/母親/兒子/女兒 哈踱,同時(shí)盤子作為一個(gè)互斥訪問的臨界區(qū)
semaphore plate=1;
semaphore apple=0;
semaphore orange=0;
dad(){
while(1){
prepare an apple;
p(plate);
put an apple开镣;
v(apple);
}
}
mom(){
while(1){
prepare an orange;
p(plate);
put an orange;
v(orange);
}
}
son(){
while(1){
p(orange);
take the apple;
v(plate);
eat;
}
}
daughter(){
while(1){
p(apple);
take the apple;
v(plate);
eat;
}
}
這里面的情況其實(shí)比較簡(jiǎn)單因?yàn)閮鹤雍团畠菏褂玫馁Y源不同所以他們之間不存在競(jìng)爭(zhēng)資源的問題邪财,而作為放水果的父親母親對(duì)盤子的訪問就要互斥進(jìn)行质欲;
- 讀者寫者問題
總共有兩組進(jìn)程,讀者/寫者怎憋,對(duì)同一個(gè)文件進(jìn)行讀寫九昧,要求有讀者在讀的時(shí)候,不可以進(jìn)行寫操作愤炸,但可以有另外的讀者同時(shí)對(duì)該文件讀取掉奄,也就是說姓建,讀寫進(jìn)程不可并發(fā)缤苫,讀進(jìn)程之間可以并發(fā)。
第一種對(duì)于寫者并不友好的方式
semaphore count=0;
semaphore mutex=1;
semaphore rw=1;
writer(){
while(1){
p(rw);
write the file;
v(rw);
}
}
reader(){
while(1){
p(mutex);
if(count==0)
p(rw);
count++;
v(mutex);
read the file;
p(mutex);
count--;
if(count==0)
v(rw);
v(mutex);
}
}
這種情況下涣狗,很容易出現(xiàn)有一個(gè)穩(wěn)定讀者而使寫進(jìn)程始終都不到處理機(jī)镀钓,從而出現(xiàn)饑餓現(xiàn)象镀迂。下面是一個(gè)相對(duì)來說比較公平的改進(jìn),在這個(gè)基礎(chǔ)之上加上對(duì)訪問順序的控制窟赏,
即如果進(jìn)程有寫請(qǐng)求后會(huì)將此寫進(jìn)程之后的所有讀請(qǐng)求阻塞,使之排在該寫進(jìn)程后面涯穷,說白了,所有人 都給我按順序排好隊(duì)塌衰,沒有人有特權(quán)蝠嘉;
semaphore w=1;
semaphore rw=1;
semaphore mutex=1;
semaphore count=0;
writer(){
while(1){
p(w);
p(rw);
write the file;
v(rw);
v(w);
}
}
reader(){
while(1){
p(w);
p(mutex);
if(count==0)
p(rw);
count++;
v(mutex);
v(w);
read the file;
p(mutex);
count--;
if(count==0)
v(rw);
v(mutex);
}
}
這里面用到的信號(hào)量w蚤告,是用來防插隊(duì)的,防止后來的讀者搶占在寫著前面获诈,使寫著得不到處理心褐,這里面用來記錄讀者數(shù)量個(gè)的計(jì)數(shù)器是一定要互斥訪問的,不然在讀進(jìn)程的并發(fā)執(zhí)行過程中就會(huì)出現(xiàn)錯(cuò)誤亡嫌。
- 哲學(xué)家進(jìn)餐問題
只有當(dāng)哲學(xué)家拿到兩個(gè)筷子的時(shí)候才可以用餐掘而,這個(gè)問題就是涉及到多個(gè)進(jìn)程(哲學(xué)家)問題,每一個(gè)哲學(xué)家即一個(gè)進(jìn)程袍睡,若采取每個(gè)哲學(xué)家先取左手邊筷子則很容易出現(xiàn)每個(gè)哲學(xué)家都拿齊了自己的左手邊的筷子而導(dǎo)致每個(gè)人都有一個(gè)筷子并被阻塞,唔認(rèn)得道第二支筷子而陷入了死鎖斑胜。
現(xiàn)以五個(gè)哲學(xué)家為例,解決此問題的一個(gè)方法就是讓哲學(xué)家一次同時(shí)拿起兩個(gè)筷子掺炭,如果不能拿到兩個(gè)覆山,就放棄,也就是說每個(gè)哲學(xué)家進(jìn)程在拿兩支筷子的過程是互斥的勋篓。
semaphore chopstick[5]={1,1,1,1,1};
semaphore mutex=1;
Pi(){
while(1){
p(mutex);
p(chopstick[i]);
p(chopstick[(i+1)%5]);
v(mutex);
take the meal;
v(chopstick[i]);
v(chopstick[(i+1)%5]);
}
}
- 吸煙者問題
這個(gè)問題里面有一個(gè)提供者譬嚣,提供三種材料,但每次只向盤子中放其中兩種材料
三個(gè)吸煙者殊鞭,每個(gè)人都只有三種材料之中的一種且都各不相同尼桶;
所以這是一個(gè)同步的問題
int random;
semaphore plate=1;
semaphore offer0=0;
semaphore offer1=0;
semaphore offer2=0
producer(){
while(1){
int random=random%3;
if(random==0)
v(offer0);
esle if(random==1){
v(offer1);
else if(random==2)
v(offer2);
p(plate);
}
}
smoker0(){
while(1){
p(offer0);
get the smoke;
v(plate);
}
}
smoker1(){
while(1){
p(offer1);
get the smoke;
v(plate);
}
}
smoker2(){
while(1){
p(offer2);
get the smoke;
v(plate);
}
}
對(duì)于一個(gè)信號(hào)量K 當(dāng)它大于零時(shí)表示還有資源剩余泵督,當(dāng)其為負(fù)數(shù)時(shí)表示系統(tǒng)中等待資源的進(jìn)程數(shù)目|K|
注意:若遇到類似生產(chǎn)者消費(fèi)者問題中的同一生產(chǎn)者對(duì)應(yīng)多個(gè)不同消費(fèi)者時(shí),要記得分情況來寫救鲤,在生產(chǎn)進(jìn)程中用信號(hào)量將多個(gè)消費(fèi)進(jìn)程分開即通過內(nèi)部的判斷 來決定執(zhí)行那個(gè)消費(fèi)者的V秩冈,這是這類問題的普遍解法。
在寫V操作的時(shí)候要清楚了解順序的問題丹锹,這是一個(gè)值得仔細(xì)思考的地方队他。
在做PV操作類的題目首先要明確,臨界區(qū)是哪塊,通常為共享緩沖區(qū)粘昨,對(duì)著干臨界區(qū)是否要互斥张肾,這個(gè)經(jīng)常忘記,在寫了同步之后就把互斥忘記了馁启。注意點(diǎn)