1. 程式人生 > >作業系統學習筆記(三)

作業系統學習筆記(三)

經典程序同步問題

1 生產者-消費者問題

生產者-消費者問題是相互合作的程序關係的一種抽象,比如輸入時,輸入程序是生產者,計算程序是消費者,輸出時,計算程序是生產者,列印程序是消費者。

解決方案一:用記錄型訊號量解決

假設生產者消費者之間有一共用緩衝池,具有n個緩衝區,利用互斥訊號量mutex實現諸程序對緩衝池的互斥作用。empty表示空緩衝池數,full表示滿緩衝池數。則可描述為:
Var mutex,empty,full:semaphore:= 1, n, 0;
		buffer:array[0,...,n-1]of item;
		in, out:integer:=0,0;//指向緩衝區的指標
		begin
			parbegin
				procedure:begin
						  repeat
							...
						  producer an item nextp //將一個單位資源放進nextp緩衝變數
						    ...
						  wait(empty);//若緩衝區有空位
						  wait(mutex);//並且緩衝區空閒
						  buffer[in] := nextp;//將nextp裡的值放進緩衝區
						  in:=(in+1)mod n;//指標指向下一個空的緩衝區
						  signal(mutex);//解鎖緩衝區
						  signal(full);//滿的緩衝區數加一
						  until false;
						  end
				consumer:begin
						 repeat
							wait(full);
							wait(mutex);
							nextc:=buffer(out);
							out:=(out+1) mod n;
							signal(mutex);
							signal(empty);
							consumer the item in nextc;
						 until false;
						 end
			parend
		end



解決方案二:利用AND訊號量解決

用SWait(empty,mutex)代替wait(empty)和wait(mutex)
用Ssignal(mutex,full)代替signal(mutex)和signal(full)
用SWait(full,mutex)代替wait(full)和wait(mutex)
用Ssignal(mutex,empty)代替signal(mutex)和signal(empty),則描述如下
		Var mutex,empty,full:semaphore:=1,n,0;
			buffer:array[0,...,n-1] of item;
			in out:integer:=0,0;
		begin
			parbegin
				producer:begin
							repeat
							...
							produce an item in nextp;
							...
							Swait(empty,mutex);
							...
							buffer(in):=nextp;
							in:=(in+1)mod n;
							Ssignal(mutex,full);
							until false;
						 end
				consumer:begin
							Swait(full,mutex);
							nextc:=buffer(out);
							out:=(out+1) mod n;
							Ssignal(mutex,empty);
							consumer the item in nextc;
							until false;
						 end
			parend
		end



解決方案三:利用管程解決


管程的語法描述:
type monitor_name = MONITOR;
	<共享變數說明>:
	define<能被其他模組引用的過程名列表>
	use<要呼叫的本模組外引用的過程列表>
	procedure<過程名>(<形式引數>):
		begin
		...
		end
	function<函式名>(<形式引數>):值型別:
		begin
		...
		end
		...
		begin
		<管程的區域性資料初始化語句序列>:
		end



則解決時首先為它們建立一個管程,並命名為ProducerConsumer,簡稱PC。其中包括兩個過程:
put(item)過程。count表示緩衝池中已有資源的數目,當count大於n時,表示緩衝池已滿。
get(item)過程。當count<=0 時,表示緩衝池已無可取資源。
PC管程描述如下:
type ProducerConsumer = monitor
		Var in,out,count:integer;
		buffer:array[0,...,n-1] of item;
		notfull,notempty:condition;
		procedure entry put(item)
			begin
				if count >= n then notfull.wait;//如果已有資源大於緩衝區數目則等待
					buffer(in):=nextp;//將緩衝變數的值放入到緩衝區
					in:=(in+1)mod n;
					count:=count+1;
					if notempty.queue then notempty.signal;//喚醒等待佇列的程序
			end
		procedure entry get(item)
			begin
				if count <= 0 then notempty.wait;//如果已有資源小於0則等待
					nextc:=buffer(out);//將緩衝區的資源送入nextc緩衝變數
					out:=(out+1)mod n;
					count:=count-1;
					if nofull.queue then notfull.signal:
			end
		begin in:=out:=0;
	cout:=0;
	end
				 
	因此生產者和消費者可以描述為:
	producer:begin
			repeat
				produce an item in nextp;
				PC.put(item);
			until false;
			end
	consumer:begin
			repeat
				PC.get(item);
				consume the item in nextc;
			until false;
			end



2 哲學家進餐的問題:

問題描述:五個哲學家共用一張圓桌,分別坐在周圍五張椅子上,在圓桌上有五個碗和五隻筷子,他們的生活方式是交替的思考和進餐。一個思考,飢餓的時候便試圖獲取
其左右離他最近的兩隻筷子,只有拿到兩隻筷子才能進餐,進餐完畢,放下筷子,繼續思考問題。

1 利用記錄型洗好解決

問題思考:筷子是臨界資源,則令一隻筷子成為一個訊號量,構成訊號量組,初始化為1,則第i加哲學家的活動可描述為:
Var chopsticks:array[0,...,4] of semaphore;
	repeat
		wait(chopsticks[i]);
		wait(chopsticks[(i+1)mod 5]);
		...
		eat;
		...
		signal(chopsticks[i]);
		signal(chopsticks[(i+1) mod 5]);
		...
		think;
	until false;


但該描述容易造成死鎖,因此提供以下幾種解決方法:
(1)至多隻允許有四位哲學家同時去拿左邊的筷子。
(2)僅當哲學家左右兩隻筷子均可用時,才允許其拿起筷子。
(3)規定奇數號哲學家先拿他左邊的筷子,而偶數則相反。

2 利用AND型訊號解決

AND同步
	Var chopsticks array of semaphore:=(1,1,1,1,1);
		processi
			repeat
			 think;
			 Sswait(chopsticks[(i+1)mod 5],chopsticks[i]);
			 eat;
			 Ssignal(chopsticks[(i+1)mod 5],chopsticks[i]);
			until false;