作業系統學習筆記(三)
阿新 • • 發佈:2019-02-15
經典程序同步問題
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;