首先我們要知道進(jìn)程同步分哪兩種
同步:進(jìn)程A向B提供數(shù)據(jù)镜豹,當(dāng)輸入緩沖空時(shí),B不能得到數(shù)據(jù)而阻塞蓝牲;反之趟脂,當(dāng)緩沖滿時(shí),A無法寫入而阻塞例衍。
互斥:A昔期、B共享打印機(jī)已卸,若A申請(qǐng)打印時(shí),打印機(jī)已分配給B硼一,則A只能阻塞累澡,等B釋放后再改為就緒。
進(jìn)程同步有四個(gè)原則般贼,為了理解這四個(gè)原則愧哟,我們首先要了解臨界資源的概念
臨界資源:一次僅允許一個(gè)進(jìn)程使用的資源,系統(tǒng)中許多硬件如打印機(jī)等哼蛆,諸多進(jìn)程之間只能用互斥的方式進(jìn)行訪問蕊梧。
同步機(jī)制四原則
1.空閑讓進(jìn):臨界區(qū)空閑時(shí),可以允許一個(gè)請(qǐng)求進(jìn)入臨界區(qū)的進(jìn)程立即進(jìn)入臨界區(qū)人芽。
2.忙則等待:當(dāng)已有進(jìn)程進(jìn)入臨界區(qū)時(shí)望几,其他試圖進(jìn)入臨界區(qū)的進(jìn)程必須等待。
3.有限等待:對(duì)請(qǐng)求訪問的進(jìn)程萤厅,應(yīng)保證能在有限時(shí)間內(nèi)進(jìn)入臨界區(qū)橄抹。
4.讓權(quán)等待:當(dāng)進(jìn)程不能進(jìn)入臨界區(qū)時(shí),應(yīng)立即釋放處理器惕味,防止進(jìn)程忙等待楼誓。
舉一個(gè)例子來形容這四個(gè)原則:當(dāng)我們?nèi)ゲ蛷d吃飯時(shí),餐廳里的座位就相當(dāng)于臨界區(qū)名挥,我們每一個(gè)人相當(dāng)于訪問臨界區(qū)的代碼疟羹,當(dāng)餐廳有空桌時(shí),我們可以進(jìn)入禀倔,也就是空閑讓進(jìn)榄融。當(dāng)餐廳沒有空桌時(shí),我們必須等待救湖,也就是忙則等待愧杯。當(dāng)沒有空桌的時(shí)候服務(wù)員會(huì)給我們一個(gè)號(hào)碼,讓我們?cè)谝贿叺戎龋皇菚r(shí)刻去問服務(wù)員有沒有空桌力九,這就是讓權(quán)等待。每次發(fā)號(hào)碼的時(shí)候服務(wù)員都會(huì)估計(jì)一下排隊(duì)時(shí)間邑闺,確保每一個(gè)排隊(duì)的人都能在有限的時(shí)間內(nèi)吃到飯(假設(shè)24小時(shí)營(yíng)業(yè))跌前,這個(gè)也就是有限等待。
接下來我們就要了解計(jì)算機(jī)是如何實(shí)現(xiàn)臨界區(qū)的互斥方法了陡舅,分軟件實(shí)現(xiàn)和硬件實(shí)現(xiàn)
軟件實(shí)現(xiàn)方法
算法一抵乓、單標(biāo)志法
設(shè)置一個(gè)公用變量turn(相當(dāng)于鑰匙),最開始的時(shí)候P1有鑰匙,進(jìn)入的時(shí)候拿鑰匙開門灾炭,訪問臨界資源章鲤,訪問結(jié)束后把鑰匙給P0。P0再拿鑰匙進(jìn)去咆贬,就實(shí)現(xiàn)了交替進(jìn)入。
但是問題在于帚呼,當(dāng)P0把鑰匙給P1后掏缎,如果P1不進(jìn)去,這時(shí)候如果P0想再進(jìn)去煤杀,手里就沒有鑰匙眷蜈,無法進(jìn)入,違背空閑讓進(jìn)原則沈自。
代碼實(shí)現(xiàn)
P0進(jìn)程:? ? ? ? ? ? ? ? ?P1進(jìn)程:
while(turn!=0);? ? ? ? ?while(turn!=1) ???? //進(jìn)入?yún)^(qū)
訪問臨界區(qū);? ? ? ? ? ? ?訪問臨界區(qū);? ? ? ? ?//臨界區(qū)
turn=1;? ? ? ? ? ? ? ? ? ? ?turn=0;? ? ? ? ? ? ?????//退出區(qū)
算法二酌儒、雙標(biāo)志先檢查
設(shè)置一個(gè)數(shù)據(jù)flag[i],表示第i個(gè)元素是否正在訪問臨界區(qū)枯途。
在每一個(gè)進(jìn)程訪問臨界資源之前忌怎,先查看一下臨界資源是否正在被訪問,若正在被訪問酪夷,則等待榴啸;否則,進(jìn)程進(jìn)入臨界區(qū)晚岭,之后修改flag[i]鸥印,表明其正在訪問臨界區(qū)。
但是問題在于坦报,當(dāng)Pi和Pj同時(shí)訪問臨界區(qū)時(shí)库说,因?yàn)槲覀冎挥性谶M(jìn)入臨界區(qū)后才會(huì)修改flag,所以同一時(shí)刻片择,可能會(huì)同時(shí)進(jìn)入臨界區(qū)潜的,違背忙則等待原則。
完整代碼
Pi進(jìn)程:????????????????Pj進(jìn)程:
while(flag[j])? ? ? ? ? ?while(flag[i])
;? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; ???????????????????????? //判斷是否有進(jìn)程在臨界區(qū)
flag[i]=TRUE;? ? ? ? flag[j]=TRUE; ????//修改flag
訪問臨界區(qū);? ? ? ? ? 訪問臨界區(qū); ????????//臨界區(qū)
flag[i]=FALSE;? ? ? ?flag[j]=FALSE; ????//退出區(qū)
算法三构回、雙標(biāo)志法后檢查
與算法二不同夏块,算法三先修改flag[i](表示想進(jìn)去的意圖),表明其想要進(jìn)去(并沒有進(jìn)去)纤掸,然后檢測(cè)對(duì)方是否想要進(jìn)去脐供,如果對(duì)方?jīng)]有想要進(jìn)去,則進(jìn)入借跪,反之政己,則等待。
這個(gè)問題就很顯而易見了掏愁,當(dāng)兩個(gè)進(jìn)程都想進(jìn)入歇由,同時(shí)都修改了各自的flag[i]卵牍,這樣兩個(gè)人都會(huì)陷入等待,導(dǎo)致了饑餓狀態(tài)沦泌。
完整代碼
Pi進(jìn)程: ???????????????? Pj進(jìn)程:
flag[i]=TRUE;? ? ? ? ?flag[j]=TRUE;? ? ? ? //修改flag
while(flag[j])? ? ? ? ? ? while(flag[i])
;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; ???????????????????????? //判斷是否有進(jìn)程在臨界區(qū)
訪問臨界區(qū);? ? ? ? ? ? ?訪問臨界區(qū); ????????//臨界區(qū)
flag[i]=FALSE;? ? ? ? ?flag[j]=FALSE;? ? ? //退出區(qū)
這里涉及到了饑餓問題糊昙,就先講一下饑餓和死鎖的概念了
饑餓:一個(gè)就緒進(jìn)程所申請(qǐng)的資源總是被優(yōu)先于自己的其他進(jìn)程所占有,而始終不能被調(diào)度執(zhí)行的狀態(tài)谢谦,稱為”饑餓”
死鎖:有可能出現(xiàn)某些進(jìn)程相互之間都在等在對(duì)方的資源且都無法運(yùn)行的局面释牺,即在進(jìn)程集合中的這些進(jìn)程處于永遠(yuǎn)的阻塞狀態(tài),稱為”死鎖”
算法四回挽、Peterson’s Algorithm
我們綜合前面三種方法没咙,設(shè)置變量turn(鑰匙),flag[i](表示想進(jìn)去的意圖)千劈,當(dāng)一個(gè)進(jìn)程到來時(shí)祭刚,將鑰匙放到另外一個(gè)人的口袋里,同時(shí)修改flag[i]墙牌,表面自身想要進(jìn)入涡驮,如果同時(shí)滿足,鑰匙在對(duì)方口袋里喜滨,并且對(duì)方也想要進(jìn)去遮怜,那么就在外面等待。如果有一項(xiàng)不滿足(鑰匙在我口袋里或者對(duì)方不想進(jìn)去或者兩者都具備)那么我就可以進(jìn)去鸿市。
也就是用flag解決互斥問題锯梁,用turn解決饑餓問題。
思考一下:假如兩個(gè)進(jìn)程同時(shí)到達(dá)焰情,兩個(gè)人都有進(jìn)去的意圖陌凳,但是無論如何,鑰匙最終都會(huì)落在一個(gè)人手里内舟,最后想進(jìn)去并且擁有鑰匙的人就進(jìn)去了合敦,不會(huì)導(dǎo)致饑餓。進(jìn)去的人出來后验游,修改flag[i]充岛,表面其自身并不想進(jìn)去,則另一個(gè)進(jìn)行跳出循環(huán)耕蝉,進(jìn)入臨界區(qū)(雖然鑰匙不在身上:D)
具體代碼
Pi進(jìn)程:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Pj進(jìn)程:
flag[i]=TURE;? ? ? ? ? ? ? ? ? ? ? ?turn=j;flag[j]=ture;turn=i;????????//修改flag崔梗,改變turn
while(flag[j]&&turn==j)? ? ? ? ? while(flag[i]&&turn=i)
;????????????????????????????????????????????;????????????????????????????????????????????//滿足兩個(gè)條件則循環(huán)
訪問臨界區(qū);? ? ? ? ? ? ? ? ? ? ? ? ? ?訪問臨界區(qū);? ? ? ? ? ? ? ? ? ? ? ? ?//臨界區(qū)
flag[i]-FALSE;????????????????????????flag[i]=FLASE;????????????????????//退出區(qū)
接下來是硬件實(shí)現(xiàn)方法
方法一、中斷屏蔽法(效率很低垒在,不好)
進(jìn)程在進(jìn)入臨界區(qū)之前先執(zhí)行”關(guān)中斷”質(zhì)量來屏蔽掉所有中斷蒜魄。進(jìn)程完成臨界區(qū)的任務(wù)后,在執(zhí)行”開中斷”執(zhí)行將中斷打開。
方法二谈为、硬件指令方法(TestAndSet指令)
為每個(gè)臨界資源設(shè)置一個(gè)s旅挤,看成一把鎖。
若s值為0(開鎖狀態(tài))伞鲫,則表示每頁(yè)進(jìn)程訪問該鎖對(duì)應(yīng)的臨界資源;
若s的值為1(關(guān)鎖狀態(tài))粘茄,則表示該鎖對(duì)應(yīng)的臨界資源已被某個(gè)進(jìn)程占用。
具體代碼
while TS (&lock) ????????//只要處在關(guān)鎖狀態(tài)就不斷循環(huán)等待秕脓,違反讓權(quán)等待
;
訪問臨界區(qū);? ? ? ? ? ? ? ? ?//臨界區(qū)
lock=FALSE;? ? ? ? ? ? ? ? //退出區(qū)
方法三驹闰、swap指令
設(shè)置一個(gè)全局變量lock,lock=0時(shí)撒会,空閑,反之师妙,有進(jìn)程诵肛。
每個(gè)進(jìn)程設(shè)置一個(gè)局部變量key,只有當(dāng)lock==0并且key==1時(shí)默穴,進(jìn)程才能進(jìn)入臨界區(qū)怔檩。
進(jìn)入臨界區(qū)后,執(zhí)行swap指令蓄诽,lock=1,key=0薛训。
退出臨界區(qū)時(shí),將lock的執(zhí)行置為0仑氛。
具體代碼
key = true; //初始化key
do{
swqp(&lock,&key);
}while(&key); ???????? ???????? //執(zhí)行完了swap之后才能進(jìn)入
進(jìn)入臨界區(qū);
lock = FALSE;? ? ? ? ? ? ? ? ? //退出的時(shí)候?qū)ock置為0