執行緒同步互斥之訊號量物件(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
以上是訊號量物件那的基本用法,更多用法可以去查閱相關的資料!