處理同步和互斥的問題,除了用到之前的軟體和硬體的方法,用的最多的還是訊號量機制。
訊號量機制是通過定義表示共享資源使用的特殊變數以及兩個標準的原語(p操作和v操作),來實現同步和互斥的。
根據訊號量的資料型別不同,我們將訊號量分為整型訊號量和記錄型訊號量。
整型訊號量
整型訊號量是一種被定義為用來表示資源數的整型量s,其值只能被wait和signal操作。s的初始值被設定為可訪問的資源數的數量。當用整型訊號量用於互斥的時候,s被初始化為1,表示臨界資源不能被多個程序同時訪問。wait,signal操作代表表示如下:
//整型訊號量
int s;
wait(s)
}//相當於p操作,程序申請乙個資源
而對於signal操作:
signal(s)//與wait操作相反,表明這個時候釋放乙個資源
記錄型訊號量struct semaphore
訊號量只能通過兩個原語操作(p,和v)來訪問它們,而pv對應的**操作如下:
/p操作的**表示
void wait(semaphore s)
//v操作的**表示
void signal(semaphore s)
顯然我們可以得出這樣乙個結論:p操作意味著釋放乙個資源,v操作意味著釋放乙個資源。當s.value <= 0時,其|s.value <= 0|的值代表的是等待佇列中等待該資源的程序數。如s.value = -8,那麼表示等待佇列中有8個程序正在等待這個臨界資源,s.value = 0,則表示資源剛好使用完畢。
利用訊號量解決互斥問題
看乙個程式段:
//程式p1
//程式p2
假設兩段程式共享乙個變數count,那麼如果程式併發執行,則可能出現兩種結果,count = 6或者count = 7;(就不分析了),但是結果肯定是唯一的。造成這個原因我們之前說過,就是因為p1在訪問臨界資源count的時候,p2也在訪問,導致前後的值不一致。所以解決的方法就是當其中乙個程序在訪問的時候,將這個變數保護起來。我們就用訊號量機制來表示一下;
下面的**是我假設執行順序是p1 -> p2.,過程看我的注釋。反過來的分析是一樣的
semaphore mutex = 1;//設定初始互斥訊號量為1
//程式p1
//程式p2
這樣,無論按什麼樣的執行順序,count的結果都是7,實現了可再現性。
注意,在解決互斥問題的時候,申請(p)的資源最後一定要釋放(v)出來,否則後序的程序不能執行。
訊號量解決同步問題
同步,是指程序間要按照一定的順序進行。有些程式並不滿足併發的條件(比如我們前面舉過的例子),因為後面的程序推進必須依賴前面程序的結果。因此必要的時候要控制程序的先後執行順序。
我們通常用前驅圖來表示程序間的同步關係。如下圖:
顯然,我們知道p2,p3可以併發執行,但是p2和p4卻不可以。我們用pv操作來描述這一過程(我們一開始設定訊號量s1 = s2 = s3 = 0)
分析:對於p1,它是程序的起始,一定要先於p2,p3,p4執行,而p2,p3併發執行,都要用到p1所提供的資源。所以p1才會先執行**,然後釋放兩個資源供p2,p4使用.這裡有個問題,就是為什麼設定訊號量為0?因為我們第一步要v(s1),初始值為0,v一下就加1,這個時候才有資源給p2去申請(p)。
對於p2,它先向p1申請到要的資源後,進入臨界區執行,然後釋放資源給p4繼續執行。
對於p3,p4,他們都順利申請到了想要的資源,但是不再釋放資源了,因為已經沒有了後續需要使用資源的程序了。
所以,我們可以得出結論,pv操作是成對出現的,有對某個資源的p操作,就一定要對某個資源的v操作。
作業系統訊號量
本文將針對較為簡單的生產者消費者問題,給出利用訊號量解決問題的方法。生產者 能產生並投放資源的程序 消費者 單純使用 消耗 資源的程序 問題表述 一組 生產者程序和一 組消費者程序 設每組有多個程序 通過緩衝區發生聯絡。生產者程序將生產的產品 資料 訊息等統稱為產品 送入緩衝區,消費者程序從中取出產...
作業系統 訊號量
代表了一類物理資源,是相應的物理資源的抽象,通常為整型或結構體型,除了初始化之外,其他情況下只能使用p v進行操作 執行一次p s 則s.value減一,若執行p s 之後s.value 0,則表示該類資源可用,否則不可用 執行一次v s 則s.value加一,若執行v操作以後,s.value的值仍...
作業系統 訊號量機制
用乙個整數型的變數作為訊號量,用來表示股系統中某種資源的數量。與普通整數變數的區別 對訊號量的操作只有三種,初始化,p操作,v操作。p操作 相當於wait原語,進入區 v操作 signal原語,相當於退出區。大體實現 wait 方法一氣呵成,避免併發導致的問題。但是不滿足 讓權等待原則 程序會處於忙...