多執行緒7 經典執行緒同步 訊號量Semaphore

2021-06-18 00:53:22 字數 3296 閱讀 5492

前面介紹了

關鍵段cs

、事件event

、互斥量mutex

在經典執行緒同步問題中的使用。本篇介紹用訊號量semaphore

來解決這個問題。

semaphore和event有個地方相同,那就是沒有owner的觀念,即thread a 所create出的semaphore,在thread b中執行releasesemaphore時,依然會增加計數器的值。而mutex和critical section則有owner概念。

首先也來看看如何使用訊號量,訊號量semaphore

常用有三個函式,使用很方便。下面是這幾個函式的原型和使用說明。

第乙個createsemaphore

函式功能:建立訊號量

函式原型:

handle

createsemaphore(

lpsecurity_attributes

lpsemaphoreattributes,

long

linitialcount,

long

lmaximumcount,

lpctstr

lpname );

函式說明:

第乙個引數表示安全控制,一般直接傳入null。

第二個引數表示初始化的訊號量個數。

第三個引數表示允許訊號量增加到的最大值。

第四個引數表示訊號量的名稱,傳入null表示匿名信號量。

第二個 opensemaphore

函式功能:開啟訊號量

函式原型:

handle

opensemaphore(

dword

dwdesiredaccess,

bool

binherithandle,

lpctstr

lpname );

函式說明:

第乙個引數表示訪問許可權,對一般傳入semaphore_all_access。詳細解釋可以檢視msdn文件。

第二個引數表示訊號量控制代碼繼承性,一般傳入true即可。

第三個引數表示名稱,不同程序中的各執行緒可以通過名稱來確保它們訪問同乙個訊號量。

第三個 releasesemaphore

函式功能:遞增訊號量的當前資源計數

函式原型:

bool

releasesemaphore(

handle

hsemaphore,

long

lreleasecount,  

lplong

lppreviouscount  );

函式說明:

第乙個引數是訊號量的控制代碼。

第二個引數表示每觸發一次所增加的個數,必須大於0且不超過最大資源數量。

第三個引數可以用來傳出先前的資源計數,設為null表示不需要傳出。

注意:當前資源數量大於0,表示訊號量處於觸發,等於0表示資源已經耗盡故訊號量處於末觸發。在對訊號量呼叫等待函式時,等待函式會檢查訊號量的當前資源計數,如果大於0(即訊號量處於觸發狀態),減1後返回讓呼叫執行緒繼續執行。乙個執行緒可以多次呼叫等待函式來減小訊號量。 

最後乙個 訊號量的清理與銷毀

由於訊號量是核心物件,因此使用closehandle()就可以完成清理與銷毀了。

在經典多執行緒問題中設定乙個訊號量和乙個關鍵段。用訊號量處理主線程與子執行緒的同步,用關鍵段來處理各子執行緒間的互斥。詳見**:

#include #include #include long g_nnum;

unsigned int __stdcall fun(void *ppm);

const int thread_num = 10;

//訊號量與關鍵段

handle g_hthreadparameter;

critical_section g_csthreadcode;

int main()

waitformultipleobjects(thread_num, handle, true, infinite);

//銷毀訊號量和關鍵段

deletecriticalsection(&g_csthreadcode);

closehandle(g_hthreadparameter);

for (i = 0; i < thread_num; i++)

closehandle(handle[i]);

return 0;

}unsigned int __stdcall fun(void *ppm)

執行結果如下圖:

可以看出來,訊號量也可以解決執行緒之間的同步問題。

再考慮這樣乙個問題:

共有write、read1、read2、read3四個執行緒,只有當write執行緒寫完之後,3個read執行緒才能讀,並且只有當3個read執行緒讀完之後,write執行緒才能寫

**如下:

在以上的程式中, 首先用

createsemaphore建立了4個訊號量,並且把h1的初始訊號量和最大訊號量個數都設為3,而將h2、h3、h4的初始訊號量和最大訊號量個數分別設為0和1,然後開啟write、read1、read2、read3四個執行緒。剛開始的時候緩衝區為空,所以read執行緒先開始執行,它呼叫了3次waitforsingleobject(pparams->h1,infinite)使得當前訊號量的個數由3個減到0個,接著開始向緩衝區中寫入資料。當寫完資料後,分別呼叫releasesemaphore將h2、h3、h4的當前訊號量個數加1,從而使得h2、h3、h4由無訊號狀態轉變為有訊號狀態,之後h2、h3、h4開始讀取緩衝區中的資料。當3個read執行緒分別讀取之後,write又開始向緩衝區中寫入資料,如此迴圈。。直到使用者按下鍵盤上的任意鍵停止。

訊號量同步多執行緒

windows.waitforsingleobject feventhandle,180000 feventhandle windows.createevent nil,false,false,pchar feventname if feventhandle thandle nil then win...

Linux多執行緒同步 訊號量

同步主線程與子執行緒 子執行緒之間的同步 使用單個訊號量 include include include include include include void ret result thread1 void ret result thread2 sem t sem void thread1fun...

Linux 多執行緒訊號量同步

p操作 v操作 include sem t sem 定義訊號量 sem init 初始化訊號量 sem wait 獲取訊號量,訊號量的數值 1 訪問共享資源 sem post 釋放乙個訊號量,及訊號量的數值 1 sem destroy 如果不再使用訊號量,則銷毀訊號量函式和posix ipc的訊號量...