進程同步和信號量

進程的同步spa

進程合做:多進程完成同一個任務 3d

 

實例1:blog

司機              售票員 隊列

while)true){          while)true){ 進程

等待 啓動車輛;           關門; 發送信號 資源

   正常運行;           售票; 文檔

   到站停車;發送信號       等待 開門; 同步

}                } it

兩個進程如何實現同步合做? 經過信號 多進程

實例2:文檔打印

問題:若是進程之間徹底不知道對方的存在,會產生怎樣的錯誤?聯繫實際

 

 

實際上的例子:生產者-消費者實例

共享數據

  這些都是用戶態

 

生產者進程

while(true){

  while(counter == BUFFER_SIZE)

     ; //阻塞  緩衝區滿,生產者停

  buffer[in] = item;

  in = (in+1)%BUFFER_SIZE;

  counter++; //發信號讓消費者走

}

 

消費者進程

while(true){

  while(counter == 0)

   ; //阻塞  緩衝區空,消費者停

  item=buffer[out];

  out = (out-1)%BUFFER_SIZE;

  counter--; //發信號讓生產者走

}

 

等待是進程同步的核心

 

什麼是進程同步?什麼地方停,什麼地方走?

進程同步 事實上就是讓進城走走停停,來保證多進程合做的合理有序

 

只發信號還不能解決所有問題

1.緩衝區滿之後生產者P1生產一個item放入,會sleep

2.有一個生產者P2生產一個item放入,會sleep

3.消費者C執行1次循環,counter == BUFFER_SIZE - 1, 發信號給P1, P1 wake up。

4.消費者C再執行1次循環,counter == BUFFER_SIZE - 2,P2不能被喚醒。

 

counter沒法區分有多少生產者進程,不只須要喚醒進程(發送信號),還須要一個量用來記錄睡眠進程的數量,來決定是否要發信號。

 

這就引出了信號量

   

從信號到信號量

不僅是等待信號,發信號? 對應睡眠和喚醒

還能記錄一些信息

  • 能記錄有2個進程等待就能夠了 能夠使用優先隊列或者是棧來存儲
  • 1.緩衝區滿,P1執行,P1 sleep,記錄下一個進程等待 sem = -1
  • 2.P2執行,P2sleep,記錄下兩個進程等待   sem = -2
  • 3.C執行1次循環,發現兩個進程等待,wakeup一個 wakeup P1 sem=-1
  • C再執行1次循環,發現一個進程等待,wakeup一個 wakeup P2 sem=0
  • C再執行1次循環4,發現沒有進程等待,sem = 1
  • P3執行

總結:

何時減一?

當有一個進程sleep,信號量-1

何時加一?

當發現信號量是負的,信號量+1,而且發信號wakeup; 若是發現信號量是正的,那麼不發信號,累加信號量。

 

問題:一種資源的數量是8,這個資源對應的信號量的當前值是2,說明():

資源的數量是8,說明初始的sem是8,當前的信號量變爲2,說明沒有進程在等待等待這個資源。

 

什麼是信號量?信號量的定義

信號量:1965年,由荷蘭學者Dijkstra提出的一種特殊變量,量用來記錄,信號用來sleep和wakeup

 

struct semaphore

{

   int value; //記錄資料個數

   PCB *queue; //記錄等待在該信號量上的進程

}

P(semaphore s); //消費資源

V(semphore s); //產生資源

 

P(semphore s)

{

   s.value--;

   if(s.value < 0){

     sleep(s.queue); 

   }

}

 

問:V(s)的代碼?

V(semphore s){

  s.value++;

  if(s.value <= 0){

   wakeup(s.queue);

  }

}

 

Producer(item){

   P(empty);

   P(mutex);

   讀入in;將item寫入到in的位置上;

   V(mutex);

   V(full);

}

 

Constumer() {

   P(full);

   P(mutex);

   讀入out;從文件out位置讀出到item;打印item;

   V(mutex);

   V(empty);

}

 

用信號量解決生產者-消費者問題

int fd = open("buffer.txt");

write(fd, 0, sizeof(int)); //寫in

write(fd, 0, sizeof(int)); //寫out

 

semaphore full = 0;

semaphore empty = BUFFER_SIZE;

semaphore mutex = 1;

 

如何理解用信號量的生產者消費者代碼?

full用來判斷是否爲空,empty用來判斷是否爲滿。經過P和V來睡眠和喚醒進程,並釋放信號量。

 

如何實現互斥訪問?

當進入緩衝區時,將mutex的值變爲0,用完以後在釋放。

相關文章
相關標籤/搜索