同步問題

對于進程這塊來說,同步問題算是一個大頭了,我也是看了好幾遍,真的服


王道里面這樣說:“如果一個操作想要取得資源你就在它前面P一下那個資源,如果一個操作產(chǎn)生了一個資源后,你就要在它后面V一下”;

這個確實,
申請資源之前看看,有沒有資源取得,有的話自然進入下一步,沒有的話,阻塞了;
生產(chǎn)了資源的,生產(chǎn)了之后V一下,這個時候上面阻塞的那個P就可以繼續(xù)執(zhí)行下去了(這也是所謂的喚醒);

幾個經(jīng)典的問題


  • 生產(chǎn)者/消費者
    這里面就有兩個進程,producer()、consumer();
    一個產(chǎn)生資源,一個取資源,還有一個用來放資源的緩沖區(qū)n個空間;
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);
      }
}

這個里面為啥要用互斥呢!mutex
因為對緩沖區(qū)的訪問得互斥,同一時刻只可以有一個進程對緩沖區(qū)操作;
同步嘛
因為每次生產(chǎn)總要看看緩沖區(qū)滿沒滿吧,緩沖區(qū)滿了就不能在放了(阻塞),或者緩沖區(qū)是不是被取空了,空了也不能再取了(阻塞);

  • 多角色消費者問題
    生產(chǎn)者 父親/母親 消費者 兒子/女兒
    父親放蘋果/母親放橘子 兒子吃橘子/女兒吃蘋果

這里涉及到四個進程,父親/母親/兒子/女兒 ,同時盤子作為一個互斥訪問的臨界區(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;
}
}

這里面的情況其實比較簡單因為兒子和女兒使用的資源不同所以他們之間不存在競爭資源的問題,而作為放水果的父親母親對盤子的訪問就要互斥進行;

  • 讀者寫者問題
    總共有兩組進程,讀者/寫者,對同一個文件進行讀寫,要求有讀者在讀的時候,不可以進行寫操作,但可以有另外的讀者同時對該文件讀取,也就是說,讀寫進程不可并發(fā),讀進程之間可以并發(fā)。
    第一種對于寫者并不友好的方式
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)有一個穩(wěn)定讀者而使寫進程始終都不到處理機,從而出現(xiàn)饑餓現(xià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);
}
}

這里面用到的信號量w,是用來防插隊的,防止后來的讀者搶占在寫著前面,使寫著得不到處理,這里面用來記錄讀者數(shù)量個的計數(shù)器是一定要互斥訪問的,不然在讀進程的并發(fā)執(zhí)行過程中就會出現(xiàn)錯誤。

  • 哲學家進餐問題
    只有當哲學家拿到兩個筷子的時候才可以用餐,這個問題就是涉及到多個進程(哲學家)問題,每一個哲學家即一個進程,若采取每個哲學家先取左手邊筷子則很容易出現(xiàn)每個哲學家都拿齊了自己的左手邊的筷子而導致每個人都有一個筷子并被阻塞,唔認得道第二支筷子而陷入了死鎖。
    現(xià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]);
}
}
  • 吸煙者問題
    這個問題里面有一個提供者,提供三種材料,但每次只向盤子中放其中兩種材料
    三個吸煙者,每個人都只有三種材料之中的一種且都各不相同;
    所以這是一個同步的問題
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);
}
}

對于一個信號量K 當它大于零時表示還有資源剩余,當其為負數(shù)時表示系統(tǒng)中等待資源的進程數(shù)目|K|
注意:若遇到類似生產(chǎn)者消費者問題中的同一生產(chǎn)者對應多個不同消費者時,要記得分情況來寫,在生產(chǎn)進程中用信號量將多個消費進程分開即通過內(nèi)部的判斷 來決定執(zhí)行那個消費者的V,這是這類問題的普遍解法。
在寫V操作的時候要清楚了解順序的問題,這是一個值得仔細思考的地方。
在做PV操作類的題目首先要明確,臨界區(qū)是哪塊,通常為共享緩沖區(qū),對著干臨界區(qū)是否要互斥,這個經(jīng)常忘記,在寫了同步之后就把互斥忘記了。注意點

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容