Linux 執行緒同步之訊號量同步

2021-06-12 03:20:48 字數 3142 閱讀 5722

linux中兩種基本的同步方法是訊號量和互斥量。這兩種方法很相似,而且它們可以相互通過對方來實現。

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

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

訊號量有兩種型別:

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

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

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

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

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

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

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

#include

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 非零,但系統還沒有支援程序共享的訊號量。

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

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 不是乙個有效的訊號量。

int sem_post(sem_t * sem);
說明

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

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

錯誤einval

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

eoverflow

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

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

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

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

**:

#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);//執行緒終止執行

}

執行結果:

Linux 執行緒同步之訊號量同步

linux中兩種基本的同步方法是訊號量和互斥量。這兩種方法很相似,而且它們可以相互通過對方來實現。下面介紹用訊號量進行同步。訊號量概念由荷蘭科學家dijkstra首先提出。訊號量是乙個特殊型別的變數,它可以被增加或者減少。但對其的關鍵訪問被保證是原子操作,即使在乙個多執行緒程式中也是如此。訊號量有兩...

執行緒同步之訊號量同步

linux中兩種基本的同步方法是訊號量和互斥量。這兩種方法很相似,而且它們可以相互通過對方來實現。現在有個圖書館,其能容納100人,現在有兩個執行緒a b,a執行緒執行 往圖書管理進入乙個人,b執行緒 從圖書館出來乙個人。那麼為了使得執行緒a在圖書館滿人的時候進入等待,而不是繼續往圖書館裡進人,使得...

Linux執行緒同步之訊號量

訊號量可以同時訪問多份資源。include intsem init sem t sem,int pshared,unsigned int value int sem destroy sem t sem int sem post sem t sem int sem wait sem t sem int...