問題描述
有一個許多進程共享的數據區,這個數據區可以是一個文件或者主存的一塊空間;有一些只讀取這個數據區的進程(Reader)和一些只往數據區寫數據的進程(Writer),此外還需要滿足以下條件:
(1) 任意多個讀進程可以同時讀這個文件;
(2) 一次只有一個寫進程可以往文件中寫;
(3) 如果一個寫進程正在進行操作,禁止任何讀進程度文件。
讀優先
一個讀者試圖進行讀操作時,如果這時正有其他讀者在進行操作,他可直接開始讀操作,而不需要等待。
readcount //讀者計數器
var rwmutex, rmutex = 1, 1;
int readcount = 0;
cobegin
procedure reader_i procedure Writer_j // i,j = 1,2,….
while true then while true then
begin begin
P(rmutex); P(rwmutex);
寫更新;
Readcount + +; V(rwmutex);
if (readcount = = 1) end
P(rwmutex);
V(rmutex);
讀數據;
P(rmutex);
Readcount - -;
if (readcount = = 0)
V(rwmutex);
V(rmutex);
end
Coend
讀優先–代碼分析
讀進程
- readcount 表示讀進程數
- rmutex 是對於計數器readcount操作的互斥信號量,rwmutex表示是否允許寫的信號量
- P(rmutex) 表示對每次有一個讀者要進行讀操作,要先對readcount 共享變量互斥操作,然後判斷當前是否是第一名讀者,如果是第一名讀者,那麼接下來將判斷rwmutex信號量得出此時是否有作者在臨界區(有的話,阻塞讀進程;無,阻塞寫進程)
- V(rmutex)表示結束對readcount共享信號量的互斥訪問
- 讀者讀完後,又開始對readcount共享信號量的互斥訪問,此時需要判斷readcount是否爲0,代表最後一個人離開讀進程區,從而判斷是否有寫進程,if yes,喚醒其中一個寫進程到臨界區
寫進程
- 確保沒有讀進程情況下,寫進程才能不阻塞
- 寫進程完畢,判斷是否有阻塞的讀進程,if yes,喚醒其中一個讀進程進入臨界區
寫優先
一個讀者試圖進行讀操作時,如果有其他寫者在等待進行寫操作或正在進行寫操作,他要等待該寫者完成寫操作後纔開始讀操作。
1)多個讀者可以同時進行讀
2)寫者必須互斥(只允許一個寫者寫,也不能讀者寫者同時進行)
3)寫者優先於讀者(一旦有寫者,則後續讀者必須等待,喚醒時 優先考慮寫者),假設讀者數是固定的
對第三點的解析:讀寫互斥,P原語,V原語操作首先考慮寫者
我們可採用下面的算法:
rwmutex:用於寫者與其他讀者/寫者互斥的訪問共享數據
rmutex:該信號量初始值設爲10,表示最多允許10個讀者進程同時進行讀操作
var rwmutex, rmutex: semaphore := 1, 10;
cobegin
procedure reader_i procedure Writer_j
begin begin // j = 1,2,….
P(rwmutex); P(rwmutex);
P(rmutex); for (i = 1;i <= 10;i + +) P(rmutex);
V(rwmutex); //禁止新讀者,並等待已進入的讀者退出讀進程
// 寫更新;
V(rmutex); for (i = 1;i <= 10;i + +) V(rmutex);
end //恢復允許rmutex值爲10,喚醒讀進程
v(rwmutex)
end
Coend