讀者-寫著問題中寫者優先的實現

期待一片自己的藍天發表於2014-07-01

讀者一寫者問題是一個用訊號量實現的經典程式同步問題。在系統中,一個資料集( 如檔案或記錄) 被幾個併發程式共享,這些執行緒分兩類,一部分只要求進行復操作,稱之為“讀者”;另一類要求寫或修改操作,我們稱之為“寫者“。

一般而言,對一個資料集,為了保證資料的完整性、正確性,允許多個讀者程式同時訪問,但是不允許一個寫者程式同其它任何一個程式(讀者或者寫者)同時訪問,而這類問題就稱之為”讀者-寫者“問題。

 

讀者優先的演算法在作業系統相關的書籍中都有介紹,這是一種最簡單的解決辦法:當沒有寫程式正在訪問共享資料集時,讀程式可以進入訪問,否則必須等待。而讀者優先的演算法存在“餓死寫者”執行緒的問題:只要有讀者不斷到來,寫者就要持久地等待,直到 所有的讀者都讀完且沒有新的讀者到來時寫者才能寫資料集。而在很多情況下我們需要避免”餓死寫者“,故而採用寫者優先演算法:

 

在寫者優先演算法中,我們要實現的目標是:

1.要讓讀者與寫者之間、以及寫者與寫者之問要互斥地訪同資料集;

2.在無寫程式到來時各讀者可同時訪問資料集;

3.在讀者和寫者都等待時訪問時寫者優先.

 

一種演算法實現:

 

我們將用兩個不同的互斥訊號量分別實現讀者與寫者間的互斥及各寫者程式間的互斥:以互斥訊號量Wmutex實現各寫者問的互斥,互斥訊號量Rmutex實現各讀者與寫者問的互斥;

 

設定兩個整型變數Wcount和Rcount分別記錄等待的寫者數和正在讀的讀者數,因Wcount、Rcount都是共享變數,因此還要設定兩個互斥訊號量Mutl和Mut2以實現程式對這兩個變最的互斥訪問.

 

用訊號量機制實現的寫者優先的演算法如  :

 

[c-sharp] view plaincopy
  1. Var Mut1,Mut2,Wmutex,Fmutex:Semaphore;    
  2.         Rcount,Wcount:integer;    
  3.         Mut1:=Mut2:=WMutex:=Fmutex:=1;    
  4.         Rcount:=Wcount:=0;    
  5. //Fmutex --> 讀者寫者互斥  
  6. //WMutex --> 寫者互斥  
  7. //Mut1 --> access to Rcount && 競爭Fmutex  
  8. //Mut2 --> access to Wcount            
  9.               
  10.             
  11. Writer:begin    
  12.         Wait(Mut1);    
  13.             Wcount:=Wcount+1;    
  14.             If Wcount=1 then Wait(Fmutex);  //如有讀者,寫者阻塞在此處  
  15.         Signal(Mut1);     
  16.         Wait(WMutex);    
  17.         寫操作;    
  18.         Signal(Wmutex);            
  19.         Wait(Mut1);    
  20.             Wcount:=Wcount-1;    
  21.             If Wcount=0 then Signal(Fmutex);     
  22.         Signal(Mut1);    
  23.         end    
  24.             
  25. Reader:begin    
  26.         Wait(Mut1);         //讀者需要先申請Mut1,如果有寫者在等待Fmutex,則讀者被阻塞,寫者優先  
  27.         Signal(Mut1);   //立即釋放Mut1,使寫者可以隨時申請到Mut1  
  28.         Wait(Mut2);    
  29.               Rcount:=Rcount+1;    
  30.               If Rcount=1 then Wait(Fmutex);  //第一個讀者進入時,申請Fmutex;如有寫者,第一個讀者會阻塞在此處  
  31.         Signal(Mut2);    
  32.         讀操作;        
  33.         Wait(Mut2);    
  34.             Rcount:=Rcount-1;    
  35.             If Rcount=0 then Signal(Fmutex);  //最後一個讀者退出時,釋放Fmutex  
  36.         Singal(Mut2);    
  37.         end    
 

 

程式碼解釋:

1: 
讀者、寫者均按照Mut1、Fmutex的順序申請訊號量。

 

2:
寫者獲得Fmutex後,直至最後一個寫者釋放Fmutex,讀者均被阻塞。
讀者獲得Fmutex後,直至最後一個讀者(不包含由於Mut1被阻塞的讀者)釋放Fmutex,寫者均被阻塞。
 
3.
讀者申請到Mut1後立即釋放;
而寫者申請到Mut1後,就一直佔用不放,直至申請到Fmutex。

 

4.總結
Fmutex的作用就是寫者、讀者間的互斥;
Mut1的額外作用就是幫助寫者優先競爭到Fmutex。

 

 

 

 

 程式碼的思路比較混亂,歡迎大家指正錯誤。

看到一篇文章,也是討論讀者寫者問題的,思路比我這篇清晰的多,文章地址如下:http://blog.csdn.net/cz_hyf/archive/2009/08/13/4443551.aspx 

相關文章