第二章 程序管理(2)
1. 程序同步的基本概念
(1)程序同步的主要任務
使併發執行的諸程序之間能有效地共享資源和相互合作,從而使程式的執行具有可再現性。
(2)臨界資源
一次僅允許一個程序使用的資源。
*理解同步
互斥:在作業系統中,當一個程序進入臨界區使用臨界資源時,另一個程序必須等待,直到佔用臨界資源的程序退出臨界區,我們稱程序之間的這種相互制約關係為“互斥”。
*同步:*多個相互合作的程序,在一些關鍵點上可能需要互相等待或互相交換資訊,這種相互制約關係稱為程序同步關係。可理解為“有序”。
(3)臨界區
每個程序中訪問臨界資源的那段程式碼叫臨界區。
為了正確同步,對臨界區的程式碼要增加控制
進入區:對欲訪問的臨界資源進行檢。若此刻未被訪問,設正在訪問的標誌
臨界區:訪問臨界資源的程式碼。
退出區:將正在訪問的標誌恢復為未被訪問的標誌
剩餘區:其餘部分
(4)同步機制應遵循的規則
1)空閒讓進:資源使用最基本原則
2)忙則等待:保證互斥
3)有限等待:合適時被喚醒防止死等
4)讓權等待:能主動釋放CPU防止忙等
(5)硬體同步機制
許多計算機提供一些特殊的硬體指令,允許對一個字中的內容進行檢測和修正,或對兩個字的內容進行交換。利用這些特殊指令解決臨界區問題。
進入臨界區往往跟其標誌有關,可將標誌看做一個鎖,“鎖開”進入並關鎖,“鎖關”必須等待,初始時鎖是開啟的。
①關中斷
進入鎖測試前關閉中斷,直到完成鎖測試並上鎖後才能開啟中斷。程序在臨界區執行期間,系統不響應中斷,從而不引發排程。
缺點:
濫用風險
關中斷時間過長會影響效率,限制CPU交叉執行能力
不適用於多CPU系統
②Test-and-Set指令
boolean TS(boolean *lock)
{
Boolean old;
old=*lock;
*lock=TRUE;
return old;
}
為一個臨界資源設定一布林變數lock,初值為false
do{
…
while TS(&lock) ;
critical section;
lock=FALSE;
remainder section;
}while(TRUE);
③利用Swap指令實現程序互斥
對換指令(intel 80x86中稱XCHG指令),用於交換兩個位元組的內容
void swap(boolean *a, boolean *b) {boolean temp; temp=*a; *a=*b; *b=temp; }
為臨界資源設定一個全域性布林變數lock=false。每個程序一個區域性布林變數key。
do{
key=TRUE;
do{
swap(&lock,&key);
}while(key!=FALSE);
// 臨界區操作;
lock=FALSE;
//剩餘區;
}while(TRUE);
2. 訊號量機制
(1) 整型訊號量
訊號量定義為一個整型量;根據初始情況賦相應的值;僅能通過兩個原子操作來訪問。
P操作
wait(S):
While S<=0 do no-op;
S:=S-1;
V操作
signal(S):
S:=S+1;
(2) 記錄型訊號量
整型訊號量符合“有限等待”原則
signal釋放資源後,當CPU被分配給等待程序後,等待程序仍可繼續執行,可以符合“有限等待”。
但整型訊號量不符合“讓權等待”原則
整型訊號量的wait操作,當s ≤0時,當前程序會佔著CPU不斷測試;
訊號量原語不能被打斷,這個佔有CPU的程序會一直不斷的佔據CPU迴圈下去,陷入忙等。
改進:條件不符時應能夠主動放棄CPU
新問題:放棄CPU的程序進入阻塞佇列:因等待某訊號量而放棄CPU的等待程序會有“若干”個,需將它們組織管理起來,並在合適的時候喚醒。
#訊號量結構資訊發生變化
不僅要有值的處理,還有佇列的處理。
此時形成記錄型資料結構,包括兩部分:
整型變數value(代表資源數目)
程序連結串列L(連結所有等待程序):
程式碼描述:
type Semaphore=record
value:integer;
L:list of PCB;
end;
操作:S.Value,S.L
Value>0,表示當前可用資源的數量;
Value≤0,其絕對值表示等待使用該資源的程序數,即在該訊號量佇列上排隊的PCB的個數。
#P、V操作也有所變化
P操作
wait():
S.value = S.value - 1;
if S.value < 0 then block(S,L)
V操作
signal():
S.value = S.value + 1;
if S.value <= 0 then wakeup(S,L)
• 定義訊號量semaphore代表可用資源實體的數量,又叫訊號燈。
• 當≥0,代表可供併發程序使用的資源實體數
• 當<0,表示正在等待使用該資源的程序數。
建立一個訊號量必須經過說明,包括
• 訊號量所代表的意義
• 賦初值
• 建立相應的資料結構,以便指向等待使用臨界區的程序。
除初值外,訊號量的值僅能由標準原子操作P、V操作來改變。 PV操作是荷蘭語通過和釋放的意思。
(3)訊號量的基本應用
1)實現程序互斥
設定一互斥訊號量mutex,初值為1。
程序i:
P(mutex);
critical section //操作共享資源R
V(mutex)
remainder section
互斥訊號量注意點:
1. 互斥訊號量mutex初值為1;
2. 每個程序中將臨界區程式碼置於P(mutex)和V(mutex)原語之間
3. 必須成對使用P和V原語(在同一程序中),不能次序錯誤、重複或遺漏:
遺漏P原語則不能保證互斥訪問
遺漏V原語則不能在使用臨界資源之後將其釋放(給其他等待的程序);
2) 實現程序間的前驅關係(有序)
前趨關係:併發執行的程序P1和P2中,分別有程式碼C1和C2,要求C1要在C2開始前完成;
為每對前趨關係設定一個同步訊號量S12,並賦初值為0。則只有V操作所在程序獲得cpu時能執行
P1 : C1 ;signal(S);
P2 : wait(S);C2 ;
控制同步順序的注意點
訊號量值為0的點是限制的關鍵所在,成對使用P和V原語(在有先後關係的兩個程序中),不能次序錯誤、重複或遺漏,否則同步順序出錯。
(4) AND型訊號量
出現原因:一些應用往往需要兩個或多個共享資源,而不是前述的一個資源。程序同時要求的共享資源越多,發生死鎖可能性越大。
解決思想:
一次性分配給程序所需資源,用完一起釋放。Wait操作時對它所有需要的資源都要判斷,有AND條件,故稱“AND同步”、“同時wait”。
Swait(S1, S2, …, Sn)
if (S1 >=1 and … and Sn>=1 )then
for i:=1 to n do
Si:= Si -1 ;
endfor
else
將程序阻塞在第一個不能滿足資源訊號量的佇列中
endif
Ssignal(S1, S2, …, Sn)
for i:=1 to n do
Si:= Si +1 ;
// 喚醒所以與si相關的阻塞程序
endfor
(5) 訊號量集
**引入原因:**每次只能獲得或釋放一個單位的資源,低效;某些時候資源分配有下限的限制;
修改:在大於可分配設定的下界值t前提下,每次可分配d個。
Swait(S1, t1, d1, …, Sn, tn, dn)
if S1>= t1 and … and Sn>= tn then
for i:=1 to n do
Si:= Si - di ;
endfor
else
…
endif
Ssignal(S1, d1, …, Sn, dn)
for i:=1 to n do
Si:= Si +di ;
….
endfor
訊號量集的一個特例
只有一個訊號量S的幾種特殊情況:
①Swait(S, d, d),,允許每次申請d個資源,若現有資源數少於d,不予分配。
②Swait(S, 1, 1),蛻化為一般的記錄型訊號量,一次申請一個,至多分配一個(S>1時可計數,或S=1時可控制互斥)。
③Swait(S, 1, 0),當S>=1時,允許多個程序進入某特定區,當S變為0後,阻止任何程序進入特定區,相當於可控開關。並不對S資源的數量產生影響。