線程的同步(四)---信號量

信號量內核對象用於對資源進行計數。它們與所有內核對象一樣,包含一個使用數量,但是它們也包含另外兩個帶符號的32位值,一個是最大資源數量,一個是當前可用資源數量。最大資源數量用於標識信標能夠控制的資源的最大數量,而當前資源數量則用於標識當前可以使用的資源的數量。

信號量的使用規則如下:
• 如果當前可用資源的數量大於0,則發出信標信號。
• 如果當前可用資源數量是0,則不發出信標信號。
• 系統決不允許當前可用資源的數量爲負值。
• 當前可用資源數量決不能大於最大資源數量。

當使用信標時,不要將信號量對象的使用數量與它的當前資源數量混爲一談。

下面的函數用於創建信標內核對象:
HANDLE CreateSemaphore(
   PSECURITY_ATTRIBUTE psa,
   LONG lInitialCount,
   LONG lMaximumCount,
   PCTSTR pszName);
psa參數指定一個SECURITY_ATTRIBUTES結構,或傳遞零值,該參數定義了信號量的安全特性。
lInitialCount參數用於指明開始時(當前)這些資源中有多少可供使用。可設置0到lMaximumCount之間的一個值。
lMaximumCount參數用於告訴系統,應用程序處理的最大資源數量是多少。由於這是個帶符號的32位值,因此最多可以擁有2147483647個資源。

pszName,指定信號量對象的名稱。

當然,通過調用OpenSemaphore函數,另一個進程可以獲得它自己的進程與現有信標相關的句柄:
HANDLE OpenSemaphore(
   DWORD fdwAccess,
   BOOL bInheritHandle,
   PCTSTR pszName);

通過調用ReleaseSemaphore函數,線程就能夠對信標的當前資源數量進行遞增:
BOOL ReleaseSemaphore(
   HANDLE hsem,
   LONG lReleaseCount,
   PLONG plPreviousCount);
該函數只是將lReleaseCount中的值添加給信標的當前可用資源數量。通常情況下,爲lReleaseCount參數傳遞1,但是,不一定非要傳遞這個值。該函數也能夠在它的*plPreviousCount中返回當前資源數量的原始值。實際上幾乎沒有應用程序關心這個值,因此可以傳遞NULL,將它忽略。

  以一個停車場的運作爲例。簡單起見,假設停車場只有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看門人允許其中三輛直接進入,然後放下車攔,剩下的車則必須在入口等待,此後來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知後,打開車攔,放入外面的一輛進去,如果又離開兩輛,則又可以放入兩輛,如此往復。
  在這個停車場系統中,車位是公共資源,每輛車好比一個線程,看門人起的就是信號量的作用。

  抽象的來講,信號量的特性如下:信號量是一個非負整數(車位數),所有通過它的線程/進程(車輛)都會將該整數減一(通過它當然是爲了使用資源),當該整數值爲零時,所有試圖通過它的線程都將處於等待狀態。在信號量上我們定義兩種操作: Wait(等待) 和 Release(釋放)。當一個線程調用Wait操作時,它要麼得到資源然後將信號量減一,要麼一直等下去(指放入阻塞隊列),直到信號量大於等於一時。Release(釋放)實際上是在信號量上執行加操作,對應於車輛離開停車場,該操作之所以叫做“釋放”是因爲釋放了由信號量守護的資源。


基本使用:
創建信號量:
HANDLE g_hSemaphore;  
g_hSemaphore = CreateSemaphore(NULL, 2, 3, NULL);//當前有2個資源可用,最多有3個資源可用

在線程中使用:

WaitForSingleObject(g_hSemaphore, INFINITE);//等待信號量>0  
。。。//資源的使用
ReleaseSemaphore(g_hSemaphore, 1, NULL);//信號量++  

使用完成要進行釋放:
CloseHandle(g_hSemaphore);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章