談談對信號量的理解

信號量的使用主要是用來保護共享資源,使得資源在一個時刻只有一個進程(線程)所擁有。

信號量的值爲正的時候,說明它空閒。所測試的線程能夠鎖定而使用它。若爲0,說明它被佔用,測試的線程要進入睡眠隊列中,等待被喚醒。ide

爲了防止出現因多個程序同時訪問一個共享資源而引起的一系列問題,咱們須要一種方法,它能夠經過生成並使用令牌來受權,在任一時刻只能有一個執行線程訪問代碼的臨界區域。函數

臨界區域是指執行數據更新的代碼須要獨佔式地執行。而信號量就能夠提供這樣的一種訪問機制,讓一個臨界區同一時間只有一個線程在訪問它,也就是說信號量是用來調協進程對共享資源的訪問的。測試

信號量是一個特殊的變量,程序對其訪問都是原子操做,且只容許對它進行等待(即P(信號變量))和發送(即V(信號變量))信息操做。線程

最簡單的信號量是隻能取0和1的變量,這也是信號量最多見的一種形式,叫作二進制信號量。而能夠取多個正整數的信號量被稱爲通用信號量。這裏主要討論二進制信號量。隊列

因爲信號量只能進行兩種操做等待和發送信號,即P(sv)和V(sv),他們的行爲是這樣的:進程

1.P(sv):若是sv的值大於零,就給它減1;若是它的值爲零,就掛起該進程的執行
2.V(sv):若是有其餘進程因等待sv而被掛起,就讓它恢復運行,若是沒有進程因等待sv而掛起,就給它加1.內存

例:A和B進程共享信號量sv,一旦A進程執行了P(sv)操做,它將獲得信號量,並能夠進入臨界區,使sv減1。而B將被阻止進入臨界區,由於當它試圖執行P(sv)時,sv爲0,它會被掛起以等待A離開臨界區域並執行V(sv)釋放信號量,這時B就能夠恢復執行。資源

Linux提供兩種信號量:

1.內核信號量,由內核控制路徑使用
2.用戶態進程使用的信號量,這種信號量又分爲POSIX信號量和SYSTEM V信號量。同步

POSIX信號量又分爲有名信號量和無名信號量it

1.有名信號量,其值保存在文件中, 因此它能夠用於線程也能夠用於進程間的同步。
2.無名信號量,其值保存在內存中。

POSIX 信號量與SYSTEM V信號量的比較

1.POSIX信號量較爲簡單,是個非負整數。經常使用於線程間同步,POSIX信號量的引用頭文件是<semaphore.h>
2.SYSTEM V信號量較爲複雜,是一個或多個信號量的集合,它對應的是一個信號量結構體,這個結構體是爲SYSTEM V IPC服務的,信號量只不過是它的一部分。經常使用於進程間同步,SYSTEM V信號量的引用頭文件是<sys/sem.h>

內核信號量
Linux內核的信號量在概念和原理上與用戶態的System V的IPC機制信號量是同樣的,可是它毫不可能在內核以外使用,它是一種睡眠鎖。若是有一個任務想要得到已經被佔用的信號量時,信號量會將其放入一個等待隊列而後讓其睡眠。當持有信號量的進程將信號釋放後,處於等待隊列中的一個任務將被喚醒(由於隊列中可能不止一個任務),並讓其得到信號量。

與自旋鎖的差別
因爲爭用信號量的進程在等待鎖從新變爲可用時會睡眠,因此信號量適用於鎖會被長時間持有的狀況;相反,鎖被短期持有時,使用信號量就不太適宜了,由於睡眠、維護等待隊列以及喚醒所花費的開銷可能比鎖佔用的所有時間表還要長。
信號量還有一個特徵,就是它容許多個持有者,而自旋鎖在任什麼時候候只能容許一個持有者。咱們遇到只有一個持有者,這種信號量叫二值信號量或者叫互斥信號量。容許有多個持有者的信號量叫計數信號量,在初始化時要說明最多容許有多少個持有者(Count值)。信號量在建立時須要設一個初始值,表示同時能夠有多個任務訪問該信號量保護的共享資源,初始值爲1就變成互斥鎖(Mutex),即同時只能有一個任務能夠訪問信號量保護的共享資源。當任務訪問完被信號量保護的共享資源後,必須釋放信號量,釋放信號量經過把信號量的值加1實現,若是信號量的值爲非正數,代表有任務等待當前信號量,所以它也喚醒全部等待該信號量的任務。
內核信號量的構成內核信號量相似於自旋鎖,由於當鎖關閉着時,它不容許內核控制路徑繼續進行。然而,當內核控制路徑試圖獲取內核信號量鎖保護的忙資源時,相應的進程就被掛起。只有在資源被釋放時,進程纔再次變爲可運行。只有能夠睡眠的函數才能獲取內核信號量;中斷處理程序和可延遲函數都不能使用內核信號量。

相關文章
相關標籤/搜索