1. 程式人生 > >執行緒同步互斥之訊號量物件(Semaphore)

執行緒同步互斥之訊號量物件(Semaphore)

  訊號量物件對執行緒的同步方式與前面幾種方法不同,訊號允許多個執行緒和程序同時使用共享資源,這與作業系統中的PV操作相同。它指出了同時訪問共享資源的執行緒最大數目。它允許多個執行緒在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大執行緒數目。在用CreateSemaphore()建立訊號量 時即要同時指出允許的最大資源計數和當前可用資源計數。一般是將當前可用資源計數設定為最大資源計數,每增加一個執行緒對共享資源的訪問,當前可用資源計數 就會減1,只要當前可用資源計數是大於0的,就可以發出訊號量訊號。但是當前可用計數減小到0時則說明當前佔用資源的執行緒數已經達到了所允許的最大數目, 不能在允許其他執行緒的進入,此時的訊號量訊號將無法發出。執行緒在處理完共享資源後,應在離開的同時通過ReleaseSemaphore()函式將當前可用資源計數加1。在任何時候當前可用資源計數決不可能大於最大資源計數。 PV操作及訊號量的概念都是由荷蘭科學家E.W.Dijkstra提出的。訊號量S是一個整數,S大於等於零時代表可供併發程序使用的資源實體數,但S小於零時則表示正在等待使用共享資源的程序數。
  P操作申請資源:


S減1; (2)若S減1後仍大於等於零,則程序繼續執行; (3)若S減1後小於零,則該程序被阻塞後進入與該訊號相對應的佇列中,然後轉入程序排程。
  V操作釋放資源:
S加1; (2)若相加結果大於零,則程序繼續執行; (3)若相加結果小於等於零,則從該訊號的等待佇列中喚醒一個等待程序,然後再返回原程序繼續執行或轉入程序排程。
這些理論知識可以去看相關的書籍,上面解釋的比我抄錄的解釋的更清楚。

#include <iostream>
#include <windows.h>
using namespace std;

static HANDLE g_hSemaphore = INVALID_HANDLE_VALUE;
static
int g_Count = 100; DWORD WINAPI Thread_A(LPVOID lpParamter); DWORD WINAPI Thread_B(LPVOID lpParamter); int main(int argc, char** argv) { HANDLE threadA = INVALID_HANDLE_VALUE; HANDLE threadB = INVALID_HANDLE_VALUE; g_hSemaphore = CreateSemaphore(NULL, 1, 20, TEXT("semaphore")); threadA = CreateThread(NULL
, 0, Thread_A, NULL, 0, NULL); threadB = CreateThread(NULL, 0, Thread_B, NULL, 0, NULL); Sleep(5000); CloseHandle(threadA); CloseHandle(threadB); return 0; } DWORD WINAPI Thread_A(LPVOID lpParamter) { long count; while(1) { WaitForSingleObject(g_hSemaphore, INFINITE); if(g_Count>0) { cout<<"thread_A:"<<g_Count<<endl; ReleaseSemaphore(g_hSemaphore, 1,&count); Sleep(1000); } else { break; } } return 0; } DWORD WINAPI Thread_B(LPVOID lpParamter) { long count; while(1) { WaitForSingleObject(g_hSemaphore, INFINITE); if(g_Count>0) { cout<<"thread_B:"<<g_Count<<endl; ReleaseSemaphore(g_hSemaphore, 1,&count); Sleep(1000); } else { break; } } return 0; }

訊號量物件的使用步驟(個人看法)
1、CreateSemaphore建立一個訊號物件;
2、呼叫WaitForSingleObject函式等待;
3、使用完後線上程呼叫ReleaseSemaphore遞增訊號量的當前資源計數 。

HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
功能:建立一個訊號量物件
引數:lpSemaphoreAttributes表示安全控制,一般直接傳入NULL。
引數:lInitialCount引數表示初始資源數量。
引數:lMaximumCount引數表示最大併發數量。
引數:lpName 引數表示訊號量的名稱,傳入NULL表示匿名訊號量。
返回值:成功返回訊號量物件的控制代碼,失敗返回NULL

函式功能:BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
功能:遞增訊號量的當前資源計數
引數:hSemaphore引數是訊號量的控制代碼。
引數:lReleaseCount引數表示增加個數,必須大於0且不超過最大資源數量。
引數:lpPreviousCount 數可以用來傳出先前的資源計數,設為NULL表示不需 要傳出。
返回值:成功為true,否則為false

  以上是訊號量物件那的基本用法,更多用法可以去查閱相關的資料!