讀者寫者問題--使用信號量的讀者優先與寫者優先程序分析

所謂誰誰優先的問題,我認爲主要體現在以下兩點中:

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 ++;
					if(readcount == i)
						semWait(wsem);
				semSignal(x);
			semSignal(rsem);//寫者搶佔訪問權的時機!
		semSignal(z);

		READUNIT();

		semWait(x);
			readcount --;
			if(readcount == 0)
				semSignal(wsem);
		semSignal(x);		
	}
}

void writer()
{
	while(true){
		semWait(y);
			writecount ++;
			if(writecount == 1)
				semWait(rsem);//第一個寫者阻塞地方
		semSignal(y);

		semWait(wsem);
			WRITEUNIT();
		semSignal(wsem);

		semWait(y);
			writecount --;
			if(writecount == 0)
				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信號隊列中至多隻有一個讀者阻塞




轉載註明出處


發佈了53 篇原創文章 · 獲贊 12 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章