程序 同步與互斥基礎

2021-07-14 04:59:42 字數 3203 閱讀 9918

臨界區:具體一點,在程式中,臨界區就是一段**區域,這段**區在任何時間點至多只有乙個程序在執行它的**。

打個比方:有個大公尺庫所,裡面裝了若干袋的大公尺,前台有個記錄冊記錄了當前庫所的庫存。當乙個員工運來大公尺時,他首先參看記錄冊中記錄了多少袋大公尺,然後將自己送來的大公尺放入倉庫,最後將自己新加入的大公尺的袋數與他之前記下的記錄冊記錄的袋數相加,並將結果更新到記錄冊中。

這個過程有個問題,你想,他記下記錄冊中的袋數,然後將送來的大公尺搬到庫所中,最後更新記錄冊。在記下記錄冊中的袋數到最後更新記錄期間要是有其他的員工過來運送大公尺怎麼辦?這裡,資料就會出現不一致了。例如:

庫所庫存:storage = 10

上午9:00,員工a來送大公尺,記下庫所的當前庫存:a=10,然後負責將大公尺搬到庫所中。

上午9:10,員工b來送大公尺,記下庫所的當前庫存:b=10,然後負責將大公尺搬到庫所中。

上午9:30,員工a搬運完送來的大公尺,數了自己送來的大公尺袋數為20,故更新storage = a + 20 = 30。

上午9:40,員工b搬運完送來的大公尺,數了自己送來的大公尺袋數為20,故更新storage = a + 20 = 30。

這樣最後的記錄冊上的庫所庫存為30,但實際因該是50才對!

回到計算機世界。

cpu會將記憶體中的內容讀到暫存器中[load指令],然後在暫存器中進行計算[一到多條計算指令],然後將計算完的結果送回到記憶體中[store指令]。在允許中斷的情況下,每一條指令週期結束的時候,cpu都會檢查是否產生了中斷,如果產生中,則轉到中斷處理程式,而在中斷返回的時候就可能發生排程,掛起當前程序,執行其它程序。

競爭條件:某個程序將乙個記憶體中的共享變數讀到暫存器中參與計算,在其將更新之後的內容寫回到記憶體之前了發生排程,切換到了其它程序,而這個新的程序需要將相同記憶體位址中的這個共享變數讀取然後操作。很明顯,若不採取必要的措施,這兩個程序就會像前面例子中提到的兩個員工一樣,錯誤的時間,錯誤的地點,做了錯誤的事情…

cpu在某個程序上執行程式,當走到臨界區時,排程發生,cpu切換到其他程序上執行程式,在某個時刻可能出現下圖中的情況:

好幾個程序都走到了臨界區前,而且當前的原子操作區是開放的,這就意味著接下來這幾個程序中誰首先被核心排程執行,誰就能夠進入到臨界區,並將原子操作區關閉,不讓其他程序進入臨界區,如下圖:

在程序退出臨界區的時候,原子操作區被開啟,再次允許其他程序進入:

一種機制,可以保證對臨界區的互斥訪問。

有這麼一條機器指令,他能將兩個變數中的內容對換。我們姑且叫他swap指令:

swap [a] [b]//將a和b儲存單位中的內容互換。

有這樣一條機器指令就能實現鎖機制了:

檔案--------

extern

bool lock = false;//全域性鎖變數,初始化為false

void _lock();

void _unlock();

檔案--------

//偽**:

#include "lock.h"

void _lock()

仔細想想,多個程序可以同時進入_lock()函式,但是能跳出迴圈的只能是最先執行到swap指令的程序,當這個程序執行完swap之後,第乙個程序的區域性棧變數key變成了false,全域性變數lock變成了true。這個程序能跳出迴圈,進入到臨界區,而其他程序執行到swap時,lock變成了true,由於他的區域性棧變數key是true,所以,他跳不出這個迴圈,會一直處在迴圈之中,等待lock變為false:

檔案--------

void _unlock()

在臨界區中的程序退出時呼叫 _unlock()函式,釋放鎖,這樣其他等待這個鎖的程序中的第乙個執行到swap指令的程序就能進入到臨界區了。這樣就實現了自旋鎖的申請與釋放。

檔案---

//大概的框架如下:

#include "lock.h"

_lock();//請求鎖

/*臨界區,do something...

*/

_unlock();//釋放鎖

有了鎖機制的支援,訊號量的實現也就好辦了,其實不過是對底層機制的應用與封裝。

檔案---

#include "lock.h"

typedef

struct semaphore;

void p(semaphore* s);

void v(semaphore* s);

檔案---

#include

"semaphore.h"

void p(semaphore* s)

_unlock();

}void v(semaphore* s)

_unlock();

}

檔案---

//大概的框架如下:

#include "semaphore.h"

extern semaphore s = ...;

...p(s);//請求乙個訊號量

/*臨界區,do something...

*/

v(s);//釋放乙個訊號量

作業系統概念.6.4.硬體同步

how are semaphores implemented?

程序同步與互斥

程序同步與互斥 首先,我們看乙個例子 程序p1 p2公用乙個變數count,初始值為0 p1 p2兩個程序的執行順序是隨機的,p1 p2可能順序執行或交錯執行。由圖可見,不同的執行順序,count值會不同,這是不允許的。在多道程式系統中,由於資源共享或程序合作,使程序間形成間接相互制約和直接相互制約...

程序同步與互斥

為什麼要引入程序同步的概念?多道程式環境下的程序併發執行,它們相互之間存在著不同的制約關係,為了理解和協調這種制約的關係,引入了程序同步的概念。臨界資源是一次只能為乙個程序使用的資源。由於臨界資源的特性,就決定了 對它的訪問必須是互斥的。在每個程序中,訪問臨界資源的那段 稱為臨界區。為了保證臨界資源...

2 程序同步與互斥

程序同步與互斥 首先,我們看乙個例子 程序p1 p2公用乙個變數count,初始值為0 p1 p2兩個程序的執行順序是隨機的,p1 p2可能順序執行或交錯執行。由圖可見,不同的執行順序,count值會不同,這是不允許的。在多道程式系統中,由於資源共享或程序合作,使程序間形成間接相互制約和直接相互制約...