在考慮寫代碼以前應該先考慮咱們要用什麼數據結構?以及該數據有什麼意義。算法
P0: { while(turn != 0) ; // critical section turn = 1; // 退出區 // remainder section } P1: { while(turn != 1) ; // critical section turn = 0; // 退出區 // remainder section }
在這裏,爲了實現互斥使用了一個共享變量turn。
爲何有效?數據結構
在任意時刻turn的取值只能爲0或1.所以條件
while(turn != X)
有且僅有一個會被知足,於是使得一個進程得以訪問臨界區。(至於turn被誰修改,何時修改,都不會對該過程產生不利影響)
有什麼不足?併發
一個標識符只有2個信息。它只能表示1.P0幹完了.2.P1幹完了。 因此當P0幹完了,P1又不幹活的時候,P0還傻傻的等P1
turn表示什麼?code
turn實際上是進程間約定的執行順序。2個進程約好輪班工做,一個在幹完活了通知另外一個,反覆交替。turn能夠理解爲許可證,只有持有turn的進程才能進去工做。就好像看病取票排隊同樣。
P0: { while(busy) ; busy=1; // critical section busy = 0; // 退出區 // remainder section } P1: { while(busy) ; busy=1; // critical section busy = 0; // 退出區 // remainder section }
這是一個典型的錯誤方法。
爲何出錯?busy表示什麼?進程
busy像是一扇大門,先進去的人從裏面反鎖不讓外面的人進來。裏面的人出來之後再從新開門。可是busy也只有2個信息量,也就是開和關。當它開門的時候沒法控制進入的數量。因此極有可能一會兒進去好多人。
可是它解決了前面的一個問題:沒法「空閒讓進」。rem
P0: { flag[0]=1;turn=0; while(flag[1]&&turn != 0) ; // critical section flag[0]=0;// 退出區 // remainder section } P1: { flag[1]=1;turn=1; while(flag[0]&&turn != 1) ; // critical section flag[1]=0;// 退出區 // remainder section }
flag是什麼?it
首先看循環等待條件flag[1]&&turn != 1
,對其取反即爲經過條件!flag[1]||turn==1
。所以進入臨界區的條件是得到許可(turn==1)或者P1空閒(!flag[0])。flag爲0表示進程很空,flag爲1表示想要進入臨界區(不必定進入)。這裏能夠形象地理解爲2個進程都盯着對方,一旦對方空了下來,就立刻衝過去。
這裏的turn有點不同!io
這裏再也不是輪班工做了。而是在表達完進入的意願後(flag置1)將turn設爲本身。說白了就是爭奪模式。最後只有一個進程搶到turn,另外一就等待對方空閒退出。
這個算法其實也不太完美,經過以上分析很容易就能知道它只容許2個進程的併發。多進程
警告:該算法自創,未來程序出了差錯,我是不會負責的class
結合一下前面幾種方法,儘量地減小信息量,還要解決多進程的併發問題。如今再整理一下思路。首先,須要一個大門。而後門後面須要取票排隊。
Pi: { while(true) { while(flag) ;//等待空閒 flag=1;//佔用 turn=i; if(turn==i) break; } // critical section flag=0;// 退出區 // remainder section }
如何工做?
利用flag控制大門開關。當裏面沒人時,立刻進入,進去後就趕忙把門反鎖(flag=1)。此時是有可能多個進程同時溜進去的,怎麼辦呢?划拳把!(turn=i)總之無論怎麼樣,最後turn爲這幫人中的某一個,所以有且僅有一個得以進入,其餘的則被轟出門外從新尋找機會。