解決競態問題之訊號量

2021-10-24 10:08:12 字數 1844 閱讀 4527

1、訊號量簡介:

訊號量是同步的一種方式,linux 核心也提供了訊號量機制,訊號量常常用於控制對共享資源的訪問。 舉乙個很常見的例子,某個停車場有 100個停車位,這 100 個停車位大家都可以用,對於大家來說這100 個停車位就是共享資源。假設現在這個停車場正常執行,你要把車停到這個這個停車場肯定要先看一下現在停了多少車了?還有沒有停車位?當前停車數量就是乙個訊號量,具體的停車數量就是這個訊號量值,當這個值到 100 的時候說明停車場滿了。停車場滿的時你可以等一會看看有沒有其他的車開出停車場,當有車開出停車場的時候停車數量就會減一,也就是說訊號量減一,此時你就可以把車停進去了,你把車停進去以後停車數量就會加一,也就是訊號量加一。這就是乙個典型的使用訊號量進行共享資源管理的案例,在這個案例中使用的就是計數型訊號量。

相比於自旋鎖,訊號量可以使執行緒進入休眠狀態,比如 a 與 b、c 合租了一套房子,這個 房子只有乙個廁所,一次只能乙個人使用。某一天早上 a去上廁所了,過了一會 b 也想用廁 所,因為 a 在廁所裡面,所以 b 只能等到 a 用來了才能進去。b 要麼就一直在廁所門口等著, 等 a出來,這個時候就相當於自旋鎖。b 也可以告訴 a,讓 a 出來以後通知他一下,然後 b 繼續回房間睡覺,這個時候相當於訊號量。可以看出,使用訊號量會提高處理器的使用效率,畢竟不用一直傻乎乎的在那裡「自旋」等待。但是,訊號量的開銷要比自旋鎖大,因為訊號量使 執行緒進入休眠狀態以後會切換執行緒,切換執行緒就會有開銷。

總結一下訊號量的特點:

1

、因為訊號量可以使等待資源執行緒進入休眠狀態,因此適用於那些占用資源比較久的場合。2、

因此訊號量不能用於中斷中,因為訊號量會引起休眠,中斷不能休眠。3、

如果共享資源的持有時間比較短,那就不適合使用訊號量了,因為頻繁的休眠、切換

執行緒引起的開銷要遠大於訊號量帶來的那點優勢。

訊號量有乙個訊號量值,相當於乙個房子有 10 把鑰匙,這 10 把鑰匙就相當於訊號量值為10。因此,可以通過訊號量來控制訪問共享資源的訪問數量,如果要想進房間,那就要先獲取 一把鑰匙,訊號量值減 1,直到 10把鑰匙都被拿走,訊號量值為 0,這個時候就不允許任何人 進入房間了,因為沒鑰匙了。如果有人從房間出來,那他要歸還他所持有的那把鑰匙,訊號量值加 1,此時有 1 把鑰匙了,那麼可以允許進去乙個人。相當於通過訊號量控制訪問資源的執行緒數,在初始化的時候將訊號量值設定的大於1,那麼這個訊號量就是計數型訊號量,計數型 訊號量不能用於互斥訪問,因為它允許多個執行緒同時訪問共享資源。如果要互斥的訪問共享資源那麼訊號量的值就不能大於 1,此時的訊號量就是乙個二值訊號量.

2、訊號量 api 函式linux 核心使用 semaphore 結構體表示訊號量,結構體內容如下所示:

struct semaphore 

;

要想使用訊號量就得先定義,然後初始化訊號量。有關訊號量的 api 函式如下所示:

訊號量的使用如下所示:

struct semaphore sem;

/* 定義訊號量 */

sema_init

(&sem,

1); /* 初始化訊號量 */

down

(&sem)

;/* 申請訊號量 */

/* 臨界區 */up(

&sem)

;/* 釋放訊號量 */

使用者態的訊號量

include int sem init sem t sem,int pshared,unsigned int value sem init 初始化乙個定位在 sem 的匿名信號量。value 引數指定訊號量的初始值。pshared 引數指明訊號量是由程序內線程共享,還是由程序之間共享。如果 psh...

解決競態問題之原子操作

原子操作簡介 原子操作就是 指不能再進一步分割的操作 一般原子操作用於 整形操作 或者 位操作 假如現在要對無符號整形變數 a 賦值,值為3,對於 c 語言來講很簡單,直接就是 a 3 但是 c 語言要先編譯為成彙編指令,arm 架構不支援直接對暫存器進行讀寫操作,比如 要借助暫存器 r0 r1 等...

訊號量管程解決同步問題

某網路系統有n個工作執行緒和1個排程服務程序,作線 星初始化時 守候佇列中等待 當使用者請求到達時,由服務程序喚醒工作執行緒執 若工執行緒守候隊列為空則則檢查請求等待佇列是否已滿 最多可存放m個使用者請求 未滿則將使用者請求放入等待佇列,否則拒絕使用者請求,工作執行緒執行結束時,檢查直請求等待佇列是...