執行緒同步之訊號量Semaphore

2021-09-25 08:14:50 字數 2357 閱讀 8386

訊號量是核心物件,它允許多個執行緒在同乙個時刻訪問同乙個共享資源,但是需要限制在同一時刻訪問此共享資源的最大執行緒數量。在建立訊號量時,要指定允許的最大資源計數和當前可用的資源數。一般將當前可用資源數設定為最大資源數,每增加乙個執行緒對共享資源的訪問,當前可用資源數減1。當可用資源計數減小到0時,則說明當前占用資源的執行緒數達到了所允許的最大數目,其他執行緒無法再進入,必須等待(阻塞)。占用資源的執行緒在處理完成後,會釋放占用的資源,此時可用資源計數加1,這時等待的執行緒佇列中,會有其中乙個執行緒被喚醒並獲取資源。

訊號量有兩種型別:二進位制訊號量計數訊號量

二進位制訊號量,只有0和1兩種取值。一般用於保護一段**使其每次只被乙個執行緒執行,這種訊號量可代替互斥鎖來實現對資源的互斥訪問。

計數訊號量,可以有更大的取值範圍,允許有限數目的執行緒共同訪問某個共享資源。

#include int sem_init(sem_t *sem, int pshared, unsigned int value);
sem即要被建立並初始化的訊號量指標;

value用來指定訊號量的初始值,也就是共享資源同時可被訪問的最大執行緒數;

第二個引數pshared需要注意,該引數設定為0時,表明該訊號量是在程序內使用,即實現執行緒之間的同步,pshared需要定義在所有執行緒都可見的位置,比如定義成全域性變數,或者動態分配在堆上的變數。該引數設定為非零值時,用於程序之間的同步,這時訊號量需要定義在共享記憶體區域中,任何可以訪問該共享記憶體區域的程序都可以通過sem_post()和sem_wait()操作該訊號量。

本篇我們只討論程序內的同步。

#include int sem_post(sem_t *sem);

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

sem_post()會使訊號量的值遞增,如果訊號量的值大於0,那麼另乙個阻塞在sem_wait()上等待該訊號的執行緒就會被喚醒,並獲取共享資源;

sem_wait()會使訊號量的值遞減。如果訊號量的值大於0,那麼執行遞減操作並立即返回;若訊號量的當前值為0,那麼該呼叫將會被阻塞,直到訊號量的值變為正值,或者被某個訊號處理函式中斷該呼叫。

sem_trywait(),與sem_wait()作用類似,不同的是當訊號量的值為0而無法執行遞減操作時,返回乙個錯誤碼(eagain),而不是阻塞宿主執行緒的執行。

sem_timedwait(),與sem_wait()作用類似,不同的是設定了乙個阻塞的時長abs_timeout,當阻塞時間超過該時長時,返回乙個etimedout錯誤。

#include int sem_destroy(sem_t *sem);
sem_destroy()用來銷毀乙個未命名的訊號量,訊號量位址由引數sem指定。只有由sem_init()函式初始化的訊號量才能呼叫sem_destroy()銷毀。訊號量在銷毀前要確保沒有其他執行緒或程序在占用它。乙個訊號量被銷毀後不可再被使用,否則會產生未知結果,被銷毀的訊號量,可通過sem_init()重新初始化後再被使用。

下面我們通過乙個例子來理解訊號量的工作機制。

假設乙個醫院的某科室有三個醫生,每個醫生每次接診乙個病人,那麼該科室最多可接診的病人數量為3。假如一段時間內,該科室僅提供20個**名額,也就是說有20人就診,那麼我們如何使用訊號量的機制來模擬該科室的就診情況呢?

/* 醫生和病人的例子:3個醫生,20個病人,每次每個醫生服務乙個病人,也就是說,最多有3個病人可同時就診 */

#include#include#include#include#include/* 訊號量定義為全域性變數 */

sem_t g_sem;

/* 定義一定時間段內,接診的病人總數量 */

const int patient_num = 20;

/* 每個執行緒模擬乙個病人的就診 */

void *patient_service(void *arg)

return null;

}int main()

usleep(50);

}/* 連線已終止的執行緒 */

for(int j = 0; j < patient_num; j++)

/* 最後釋放訊號量 */

sem_destroy(&g_sem);

return 0;

}

執行結果:

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

前面介紹了 關鍵段cs 事件event 互斥量mutex 在經典執行緒同步問題中的使用。本篇介紹用訊號量semaphore 來解決這個問題。semaphore和event有個地方相同,那就是沒有owner的觀念,即thread a 所create出的semaphore,在thread b中執行rel...

執行緒同步之訊號量同步

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

執行緒同步之訊號量

什麼是訊號量 linux sem 訊號量是一種特殊的變數,訪問具有原子性,用於解決程序或執行緒間共享資源引發的同步問題。使用者態程序對 sem 訊號量可以有以下兩種操作 等待訊號量 當訊號量值為 0 時,程式等待 當訊號量值大於 0 時,訊號量減 1,程式繼續執行。傳送訊號量 將訊號量值加 1 通過...