轉自http://www.linuxso.com/linuxbiancheng/13098.html
千萬要注意:readcount,writecount要設成共享變量(因為是進程),要不然可能會導致死鎖
所謂誰誰優先的問題,我認為主要體現在以下兩點中:
1.當低優先級進程(線程)獲得臨界區時,高優先級進程能很快從低優先級的進程中搶得訪問權。
2.當高優先級的進程獲得臨界區訪問權時,低優先級得等到高優先級全部訪問完的空閑時間才能搶得訪問權。
這兩點中, 第一點一定得要,不然無法體現出優先的意思 。
第二點可以根據程序的需要決定。
程序摘自:《操作系統精髓與設計原理》
/* program readersandwriters*/ //讀者優先,經過我修改了一點 int readcount = 0; semaphore x = 1,z = 1, wsem = 1; void reader() { while(true){ semWait(x); readcount ++ ; if(readcount == 1) semWait(wsem); semSignal(x); READUNIT();//讀數據 semWait(x); readcount --; if(readcount == 0) semSignal(wsem); semSignal(x); } } void writer() { while(true){ semWait(z);//自己加的,不過這樣降低了寫操作的效率,但滿足了以上2點。去除z信號后,就只滿足第1點,可以自己分析分析 semWait(wsem); WRITEUNIT();//寫數據 semSignal(wsem); semSignal(z); } }
程序中semWait 就是指信號量P 操作, semSignal 就是指V
首先明白一點 如果某一信號初始值為1 ,且在一個函數中是P,V操作是成對出現 ,那么這個信號量就是用來起互斥作用!
信號量x ,是用來保證readCount 自加自減操作和if條件語句操作的原子性。
來分析下為什么這個程序是讀優先呢?
1.考慮下這種情況:如果讀者已經獲得臨界區的訪問權,那么當讀者連續不斷時(即中間間隔小),也就是說當一個進程讀完前,另一個進程也進入到了臨界區。 此時的話,任一時間在臨界區中的寫進程者會大於一 。 即使來了寫進程,也只能有一個寫者阻塞在wsem信號中,其余全阻塞在z信號中。。。直到某一時刻,無讀者在臨界區時,才有機會寫臨界區。
2.在考慮一種情況:寫進程已經獲得了臨界區的訪問權,且寫進程也很密集。 此時讀進程能不能優先得到訪問權而不用等到寫進程全部訪問完呢?
答案是能。 寫進程很多,那么一次又只能有一個寫進程訪問臨界區。則其余的寫進程都會在z信號中阻塞,排隊且。 如果讀進程也想訪問了,讀進程就會在wsem信號中阻塞排隊即只有讀進程會在wsem中阻塞排隊。 注意:當此時的寫進程一旦完成訪問臨界區WRITEUNIT . 下一句semSignal(wsem) , 好, 此時阻塞在wsem隊列中的讀進程就搶得到臨界區的訪問權。。
綜上所述:在讀者優先的程序中:寫進程只有等待無讀者訪問臨界區的時刻,才能得到訪問權 ; 讀進程在任意時候都可以得到訪問權。
阻塞在wsem隊列中最多只有一個寫者 ,其余的寫者阻塞在z信號中。 wsem隊列中當然最多可能有有限個寫者(因為寫者能有很短的時候內得到訪問權)
//寫者優先
/*program readersandwriters*/
//寫者優先
int readcount , writecount;
semaphore x = 1, y = 1, z = 1, wsem = 1 , rsem = 1;
void reader()
{
while(true){
semWait(z);//z信號用來保證阻塞在rsem信號中排隊的讀者至多只有一個。其余的阻塞在z上。
semWait(rsem);
semWait(x);//保證下面3句操作的原子性
readcount ++;//在這里,當有寫者出現時,由於rsem的阻塞,readcount的值不會大於1
if(readcount == i)//i應該是1才對
semWait(wsem);//為了讓真正執行READUNIT()時沒人打擾
semSignal(x);
semSignal(rsem);//寫者搶占訪問權的時機!
semSignal(z);
READUNIT();
semWait(x);
readcount --; //由於上面readcount只能為1,所以下面語句必然執行
if(readcount == 0)
semSignal(wsem);
semSignal(x);
}
}
void writer()
{
while(true){
semWait(y);
writecount ++;
if(writecount == 1)
semWait(rsem);//第一個寫者阻塞地方
semSignal(y);
semWait(wsem);//為了讓真正執行WRITEUNIT()時沒人打擾
WRITEUNIT();
semSignal(wsem);
semWait(y);
writecount --;
if(writecount == 0)//最后一個寫者才釋放rsem,這時讀者才有機會訪問,讀者也才有機會semWait(wsem) ,否則在沒機會semWait(wsem),寫者當然可以繼續
semSignal(rsem);
semSignal(y);
}
}
同前面一樣, y是用來保護寫者中對writecount操作的原子性。
1.當讀者獲得了訪問臨界區的權利時,且讀者進程訪問的很密集時(即很多讀者都需要訪問),寫者如何搶得訪問權。
當讀者獲得訪問權時即有一個進程正在執行READUINT操作時。和上一個讀者優先程序中的寫者差不多,如果沒有寫者,那么讀者就能一個接一個到達臨界區訪問。但是因為READUINT操作前由於有z信號和rsem信號的互斥作用。使得讀者一個只有一個通過這一段代碼,其余的者阻塞在z信號中。進入臨界區時是依次進入的(但出來不一定是先進先出) 。 一旦此時來了一個寫者,他就會阻塞在rsem信號中。等會此時的讀者剛一執行完semSignal(rsem)時,那么寫者就得到rsem信號可以繼續執行了。然后寫者就只用等待讀者中已經進入臨界區的出來就能執行了。
2.當寫者獲得臨界區的訪問權時,讀者只能等到臨界區空閑時才能得到臨界區訪問權。
因為當寫者獲得臨界區時,所有的讀者都會阻塞在z信號和rsem信號中。 而只有最后一個寫者訪問完臨界區時,才會semSignal(rsem), 使得阻塞在rsem中唯一的讀者獲得臨界區訪問權。
z信號的作用是 當讀者獲得權限時, 此時來的寫者不用等待他前面所有的讀者都訪問完才訪問 。 因為z信號使得在rsem信號隊列中至多只有一個讀者阻塞
轉載注明出處
