: 讀者寫者問題
來源:互聯網
上載者:User
多進程對共用資源互斥訪問及進程同步的經典問題 設有一檔案F,多個並發讀進程和寫進程都要訪問,要求:(1)讀寫互斥(2)寫寫互斥(3)允許多個讀進程同時訪問採用記錄型訊號量機制解決 較常見的寫法:semaphore fmutex=1, rdcntmutex=1;
//fmutex --> access to file; rdcntmutex --> access to readcount
int readcount = 0;
void reader(){
while(1){
wait(rdcntmutex);
if(0 == readcount)wait(fmutex);
readcount = readcount + 1;
signal(rdcntmutex);
//Do read operation ...
wait(rdcntmutex);
readcount = readcount - 1;
if(0 == readcount)signal(fmutex);
signal(rdcntmutex);
}
}
void writer(){
while(1){
wait(fmutex);
//Do write operation ...
signal(fmutex);
}
}讀進程只要看到有其他讀進程正在訪問檔案,就可以繼續作讀訪問;寫進程必須等待所有讀進程都不訪問時才能寫檔案,即使寫進程可能比一些讀進程更早提出申請。所以以上解法實際是 讀者優先 的解法。如果在讀訪問非常頻繁的場合,有可能造成寫進程一直無法訪問檔案的局面.... 為瞭解決以上問題,需要提高寫進程的優先順序。這裡另增加一個排隊訊號量:queue。讀寫進程訪問檔案前都要在此訊號量上排隊,通過區別對待讀寫進程便可達到提高寫進程優先順序的目的。另外再增加一個 writecount 以記錄提出寫訪問申請和正在寫的進程總數:semaphore fmutex=1, rdcntmutex=1, wtcntmutex=1, queue=1;
//fmutex --> access to file; rdcntmutex --> access to readcount//wtcntmutex --> access to writecount
int readcount = 0, writecount = 0;
void reader(){
while(1){
wait(queue);
wait(rdcntmutex);
if(0 == readcount)wait(fmutex);
readcount = readcount + 1;
signal(rdcntmutex);
signal(queue);
//Do read operation ...
wait(rdcntmutex);
readcount = readcount - 1;
if(0 == readcount)signal(fmutex);
signal(rdcntmutex);
}
}
void writer(){
while(1){
wait(wtcntmutex);
if(0 == writecount)wait(queue);
writecount = writecount + 1;
signal(wtcntmutex);
wait(fmutex);
//Do write operation ...
signal(fmutex);
wait(wtcntmutex);
writecount = writecount - 1;
if(0 == writecount)signal(queue);
signal(wtcntmutex);
}
}每個讀進程最開始都要申請一下 queue 訊號量,之後在真正做讀操作前即讓出(使得寫進程可以隨時申請到 queue)。而只有第一個寫進程需要申請 queue,之後就一直佔著不放了,直到所有寫進程都完成後才讓出。等於只要有寫進程提出申請就禁止讀進程排隊,變相提高了寫進程的優先順序。 通過類似思想即可實現讀寫進程的公平競爭:semaphore fmutex=1, rdcntmutex=1, queue=1;
//fmutex --> access to file; rdcntmutex --> access to readcount
int readcount = 0;
void reader(){
while(1){
wait(queue);
wait(rdcntmutex);
if(0 == readcount)wait(fmutex);
readcount = readcount + 1;
signal(rdcntmutex);
signal(queue);
//Do read operation ...
wait(rdcntmutex);
readcount = readcount - 1;
if(0 == readcount)signal(fmutex);
signal(rdcntmutex);
}
}
void writer(){
while(1){
wait(queue);
wait(fmutex); signal(queue);
//Do write operation ...
signal(fmutex); }
}讀進程沒變,寫進程變成在每次寫操作前都要等待 queue 訊號量。 課本上一般只會寫第一種解法吧。看了後兩種方法即可發現,在第一個解法中,fmutex 訊號量實際是雙重身份,首先實現對檔案的互斥訪問,其次起到了和後面排隊訊號量 queue 相同的作用,只不過在那種排序下只能是讀者優先。如果直接看過後兩種解法,應該會有更清楚的理解吧。