同步和訊號量

2021-07-04 07:37:45 字數 3398 閱讀 9540

下面介紹用訊號量進行同步。

訊號量概念由荷蘭科學家dijkstra首先提出。訊號量是乙個特殊型別的變數,它可以被增加或者減少。但對其的關鍵訪問被保證是原子操作,即使在乙個多執行緒程式中也是如此。

訊號量有兩種型別:

(1)二進位制訊號量。它只有0和1兩種取值。

(2)計數訊號量。它可以有更大的取值範圍。

如果要用訊號量來保護一段**,使其每次只能被乙個執行執行緒執行,就要用到二進位制訊號量、。

如果要允許有限數目的執行緒執行一段指定的**,就需要用到計數訊號量。

由於計數訊號量並不常用,而且它實際上僅僅是二進位制訊號量的一種擴充套件,這裡之介紹二進位制訊號量。

訊號量函式的名字都以sem_開頭。執行緒中使用的基本函式有4個。

注意,需要包含標頭檔案:

[cpp]view plain

copy

print?

#include

[cpp]view plain

copy

print?

int sem_init(sem_t *sem, int pshared, unsigned int value);  

函式解釋:sem_init() 初始化乙個定位在 sem 的匿名信號量。value 引數指定訊號量的初始值。 pshared 引數指明訊號量是由程序內線程共享,還是由程序之間共享。如果 pshared 的值為 0,那麼訊號量將被程序內的執行緒共享,並且應該放置在所有執行緒都可見的位址上(如全域性變數,或者堆上動態分配的變數)。

如果 pshared 是非零值,那麼訊號量將在程序之間共享,並且應該定位共享記憶體區域(見 shm_open(3)、mmap(2) 和 shmget(2))。(因為通過 fork(2) 建立的孩子繼承其父親的記憶體對映,因此它也可以見到這個訊號量。)所有可以訪問共享記憶體區域的程序都可以使用sem_post(3)、sem_wait(3) 等等操作訊號量。初始化乙個已經初始的訊號量其結果未定義。

返回值

sem_init() 成功時返回 0;錯誤時,返回 -1,並把 errno 設定為合適的值。

錯誤

einval

value 超過 sem_value_max。

enosys

pshared 非零,但系統還沒有支援程序共享的訊號量。

下面是控制訊號量的兩個函式:

[cpp]view plain

copy

print?

int sem_wait(sem_t * sem);  

函式說明

sem_wait函式也是乙個原子操作,它的作用是從訊號量的值減去乙個「1」,但它永遠會先等待該訊號量為乙個非零值才開始做減法。也就是說,如果你對乙個值為2的訊號量呼叫sem_wait(),執行緒將會繼續執行,這訊號量的值將減到1。如果對乙個值為0的訊號量呼叫sem_wait(),這個函式就 會地等待直到有其它執行緒增加了這個值使它不再是0為止。如果有兩個執行緒都在sem_wait()中等待同乙個訊號量變成非零值,那麼當它被第三個執行緒增加 乙個「1」時,等待執行緒中只有乙個能夠對訊號量做減法並繼續執行,另乙個還將處於等待狀態。

返回值

所有這些函式在成功時都返回 0;錯誤保持訊號量值沒有更改,-1 被返回,並設定 errno 來指明錯誤。

錯誤

eintr

這個呼叫被訊號處理器中斷,

einval

sem 不是乙個有效的訊號量。

[cpp]view plain

copy

print?

int sem_post(sem_t * sem);   

說明sem_post函式的作用是給訊號量的值加上乙個「1」,它是乙個「原子操作」---即同時對同乙個訊號量做加「1」操作的兩個執行緒是不會衝突的;而同 時對同乙個檔案進行讀、加和寫操作的兩個程式就有可能會引起衝突。訊號量的值永遠會正確地加乙個「2」--因為有兩個執行緒試圖改變它。

返回值sem_post() 成功時返回 0;錯誤時,訊號量的值沒有更改,-1 被返回,並設定 errno 來指明錯誤。

錯誤einval

sem 不是乙個有效的訊號量。

eoverflow

訊號量允許的最大值將要被超過。

[cpp]view plain

copy

print?

int sem_destroy (sem_t *sem);  

這個函式也使用乙個訊號量指標做引數,歸還自己戰勝的一切資源。在清理訊號量的時候如果還有執行緒在等待它,使用者就會收到乙個錯誤。

與其它的函式一樣,這些函式在成功時都返回「0」。

下面主線程中建立了乙個新執行緒,用來統計輸入的字串中字元的個數。訊號量用來控制兩個執行緒對儲存字串陣列的訪問。

**:[cpp]view plain

copy

print?

#include 

#include 

#include 

#include 

#include 

#include 

//執行緒函式 

void *thread_function(void *arg);  

sem_t bin_sem;//訊號量物件

#define work_size 1024

char work_area[work_size];//工作區

int main()  

//建立新執行緒

res = pthread_create(&a_thread,null,thread_function,null);  

if(res)  

printf("input some text.enter 'end' to finish\n");  

while(strncmp("end",work_area,3) != 0)  

printf("waiting for thread to finish\n");  

//等待子執行緒結束,收集子執行緒資訊

res = pthread_join(a_thread,&thread_result);  

if(res)  

printf("thread joined\n");  

//銷毀訊號量物件

sem_destroy(&bin_sem);  

exit(exit_success);  

}  void *thread_function(void *arg)  

pthread_exit(null);//執行緒終止執行

文章出處:

同步 訊號量

include stdafx.h include includeusing namespace std int number 1 定義全域性變數 handle hsemaphore 定義訊號量控制代碼 unsigned long stdcall threadproc1 void lp long co...

執行緒訊號量同步

thread sem.c include include include include define thread number 3 define repeat number 3 define delay time levels 10.0 sem t sem thread number void ...

執行緒同步 訊號量

執行緒同步方法 訊號量不常用,找到個帖子不錯,記錄一下!依賴的標頭檔案 include 函式宣告 sem t 表示訊號量 int sem init sem t sem,int pshared,unsigned int value 名稱 sem init 功能 initialize an unname...