進程同步
兩種制約關係
間接相互制約關係:同處於一個系統中的進程,必然共享着某種系統資源。所謂間接相互制約即源於這種資源共享。例如,有兩個進程A和B,如果在A進程提出打印請求時,系統已將唯一的一臺打印機分配給了進程B,則此時進程A只能阻塞;一旦進程B將打印機釋放,才能使A進程由阻塞改爲就緒狀態。(進程互斥)
(就是兩個進程共同競爭一個資源,當A釋放了共享資源後B才能繼續進行)
直接相互制約關係:這種制約源於進程間的合作。例如C進程因得不到A進程的數據而阻塞。(進程同步)
(兩者是某種順序關係,A做完B才能繼續)
臨界資源
臨界資源:一次僅允許一個進程使用的資源。
許多物理設備,如輸入機、打印機、磁帶機等都具有這種性質。
軟件資源,如公用變量、數據、表格、隊列等也都具有這一特點。
諸進程之間應通過互斥方式,實現對臨界資源的共享。
臨界區
不論是硬件臨界資源,還是軟件臨界資源,多個進程必須互斥地對它進行訪問。
臨界區:每個進程中訪問臨界資源的那段代碼稱爲臨界區。
每個進程進入臨界區之前,應先對欲訪問的臨界資源進行檢查,看它是否正被訪問。如果此刻該臨界資源未被訪問,進程便可進入臨界區對該資源進行訪問,並設置它正被訪問的標誌;如果此刻該臨界資源正被某進程訪問,則本進程不能進入臨界區。
同步機制的四個準則
- 空閒讓進:當無進程處於臨界區時,應允許一個請求進入臨界區的進程進入臨界區;
- 忙則等待:當已有進程進入臨界區時,其他試圖進入臨界區的進程必須等待;
- 有限等待:對要求訪問臨界資源的進程,應保證在有限時間內能進入自己的臨界區,以免陷入“死等”狀態;
- 讓權等待:當進程不能進入自己的臨界區時,應立即釋放處理機,以免進程陷入“忙等”。
信號量機制
整型信號量
思想:定義一個整型量S,除初始化外,僅能通過兩個標準的原子操作wait(S)和signal(S)來訪問。
wait(S): {
while S≤0; /*do no-op*/
S--;
}
signal(S): {
S++;
}
缺點:當s<=0時,會進入死循環,一直佔用CPU,浪費資源。因此,該機制並未遵循“讓權等待”的準則,而是使進程處於“忙等”的狀態。
記錄型信號量
思想:用整型變量value代表資源的數目。用進程鏈表L來鏈接等待訪問臨界資源的進程。
記錄型信號量的定義:
typedef struct {
int value;
struct process_control_block *list;
}semphore;
臨界資源阻塞隊列:
記錄型信號量的P、V操作
wait(semaphare *S)
{
S->value--;
if (S->value<0) block(S->list);
}
signal(semphore *S)
{
S->value++;
if (S->value≤0) then wakeup(S->list);
}
說明
S->value的初值表示系統中某類資源的數目,因而又稱爲資源信號量,對它的每次wait操作,意味着進程請求一個單位的該類資源,使系統中可供分配的資源數減少一個,因此S->value–;
每次執行完wait操作後,若S->value<0時,說明該類資源已分配完畢,因此進程應調用block原語,進行自我阻塞,放棄處理機,並插入到信號量鏈表S->list中。此時S->value的絕對值表示在該信號量鏈表中已阻塞進程的數目。
每次執行signal操作表示資源數目加1,若加1後仍有S->value≤0時,則表示在該信號量鏈表中,仍有等待該資源的進程被阻塞,故還應調用wakeup原語,將S->list鏈表中的第一個等待進程喚醒。
若S->value的初值爲1,表示只允許一個進程訪問臨界資源,此時的信號量轉化爲互斥信號量。
AND型信號量
思想:將進程在整個運行過程中需要的所有資源,一次性全部地分配給進程,待進程使用完成後再一起釋放。只要尚有一個資源未能分配給進程,其他所有可能爲之分配的資源,也不分配給它。亦即,對若干個臨界資源的分配,採取原子操作方式:要麼全部分配給進程,要麼一個也不分配。
Swait(S1,S2,…,Sn)
{ while (TRUE)
{
if (S1≥1&&… &&Sn≥1){
for (i=1;i<=n;i++)
Si--;
break;
}
else {
place the process in the waiting queue associated with the first Si found with Si<1, and set the program count of this process to the beginning of Swait operation
將進程放入第一個Si<ti的等待隊列中,並且將程序指針指向該進程的Swait操作開始處;
}
}
}
Ssginal(S1,S2,…,Sn)
while (TRUE){
for(i:=1;i<=n;i++){
Si++;
remove all the process waiting in the queue associated with Si into the ready queue
將與Si 相關的等待隊列中的進程移到就緒隊列
}
}
}
信號量集
思想:若進程一次需要申請多類臨界資源,則在進行臨界資源分配時,先測試各類臨界資源是否大於其下限值。若低於下限值,則不予分配。
以下的程序中,S爲信號量,d爲需求值,t爲下限值。
Swait(S1,t1,d1,…,Sn,tn,dn)
while (TRUE){
if (S1≥t1 && … && Sn≥tn )
for (i=1;i<=n;i++) Si:=Si-di;
break;
}
else {
Place the executing process in the waiting queue of the first Si with Si<ti and set its program counter to the beginning of the Swait Operation.
將正在執行的進程移入第一個Si<ti的等待隊列中,並將程序指針指向該進程中Swait操作開始處
}
}
}
Ssignal(Si,di,…,Sn,dn)
{ while (TRUE)
{
for (i=1;i<=n;i++) {
Si:=Si+di;
Remove all the process waiting in the queue associated with Si into the ready queue
將與Si相關的等待隊列中的所有進程移到就緒隊列
}
}
}
信號量機制的應用
實現進程互斥
爲使得多個進程能互斥地訪問某臨界資源,只需爲該資源設置一互斥信號量mutex,並設其初始值爲1,然後將各進程訪問該資源的臨界區CS置於wait(mutex)和signal(mutex)操作之間即可。
實現前趨
技巧:後進程實現P(wait)操作,前進程實現V(signal)操作。
大家覺得有幫助的請點個贊啊👍