CreateSemaphore() 創建一個信號量
OpenSemaphore() 打開一個信號量
WaitForSingleObject() 等待信號量
ReleaseSemaphore() 釋放信號量
#include <windows.h>
#include <iostream>
using namespace std;
HANDLE g_hSemaphore = NULL;
int tickets = 100;
DWORD WINAPI FUNCPROC1(LPVOID) {
while (TRUE) {
WaitForSingleObject(g_hSemaphore, INFINITE);
if (tickets > 0) {
cout << "thread1 sell ticket: "<<tickets-- << endl;
ReleaseSemaphore(g_hSemaphore, 1, NULL);
}
else {
ReleaseSemaphore(g_hSemaphore, 1, NULL);
break;
}
}
return 0;
}
DWORD WINAPI FUNCPROC2(LPVOID) {
while (TRUE) {
WaitForSingleObject(g_hSemaphore, INFINITE);
if (tickets > 0) {
cout << "thread2 sell ticket: " << tickets-- << endl;
ReleaseSemaphore(g_hSemaphore, 1, NULL);
}
else {
ReleaseSemaphore(g_hSemaphore, 1, NULL);
break;
}
}
return 0;
}
int main()
{
//設置信號量的初始計數和最大計數都爲1
g_hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
HANDLE hThread1 = CreateThread(NULL, 0, FUNCPROC1, NULL, 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, FUNCPROC2, NULL, 0, NULL);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
CloseHandle(hThread1);
CloseHandle(hThread2);
CloseHandle(g_hSemaphore);
return 0;
}
總結:
1、互斥量、事件、信號量都是內核對象,可用於進程間的線程同步;而臨界區是進程內對象,只能用於進程內的線程同步。互斥量與臨界區的作用非常相似,但互斥量是可以命名的,也就是說它可以跨越進程使用。所以創建互斥量需要的資源更多,如果只爲了在進程內部使用的話,臨界區會帶來速度上的優勢並能夠減少資源佔用量。因爲互斥量是跨進程的,互斥量一旦被創建,就可以通過名字打開它。
2、事件和其他幾個同步方法的不同在於事件的主要作用不是保護共享的資源,而是用於等待某個事件和在特定的事件發生時發送信號,以協調線程之間的動作。
3、信號量與其他同步方法的區別在於它允許一個以上的線程同時訪問共享資源,而其他線程同步方法都保證同時只能有一個線程訪問共享的資源。信號量主要是用於資源計數,能夠控制有限用戶使用資源。通過互斥量可以指定資源被獨佔的方式使用,但如果有下面一種情況通過互斥量就無法處理,比如現在一位用戶購買了一份三個併發訪問許可的數據庫系統,可以根據用戶購買的訪問許可數量來決定有多少個線程/進程能同時進行數據庫操作,這時候如果利用互斥量就沒有辦法完成這個要求,信號量對象可以說是一種資源計數器。