推薦參考博客:秒殺多線程第八篇 經典線程同步 信號量Semaphore
首先先介紹和windows信號量有關的兩個API:創建信號量、釋放信號量
HANDLE WINAPI CreateSemaphore( msdn官網解釋
_In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes
_In_ LONG lInitialCount,
_In_ LONG lMaximumCount,
_In_opt_ LPCTSTR lpName
);
第一個參數:安全屬性,如果為NULL則是默認安全屬性
第二個參數:信號量的初始值,要>=0且<=第三個參數
第三個參數:信號量的最大值
第四個參數:信號量的名稱
返回值:指向信號量的句柄,如果創建的信號量和已有的信號量重名,那么返回已經存在的信號量句柄
BOOL WINAPI ReleaseSemaphore( msdn官網解釋
_In_ HANDLE hSemaphore,
_In_ LONG lReleaseCount,
_Out_opt_ LPLONG lpPreviousCount
);
第一個參數:信號量句柄
第二個參數:釋放后,信號量增加的數目
第三個參數:信號量增加前的值存放的地址,如果不需要則為NULL
返回值:釋放是否成功
以上兩個函數頭文件:windows.h (另外還有個函數OpenSemaphore()可以打開其它進程創建的信號量) 本文地址
下面通過一個例子來說明信號量如何使用,這是一道IT公司筆試題:編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推。
分析:這里我們要讓三個線程按順序依次打印ABC,即當一個線程在打印A時,另外兩個線程不能夠打印,而且打印完A以后,接下來必須打印B。我們使用三個信號量分別控制A B C的打印,打印完A就釋放B的信號量,打印完B就釋放C的信號量,打印完C就釋放A的信號量。具體見下面代碼:
#include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std;
HANDLE hsem1,hsem2,hsem3;
//線程綁定的函數返回值和參數是確定的,而且一定要__stdcall
unsigned __stdcall threadFunA(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hsem1, INFINITE);//等待信號量
cout<<"A";
ReleaseSemaphore(hsem2, 1, NULL);//釋放信號量
}
return 1;
}
unsigned __stdcall threadFunB(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hsem2, INFINITE);//等待信號量
cout<<"B";
ReleaseSemaphore(hsem3, 1, NULL);//釋放信號量
}
return 2;
}
unsigned __stdcall threadFunC(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hsem3, INFINITE);//等待信號量
cout<<"C";
ReleaseSemaphore(hsem1, 1, NULL);//釋放信號量
}
return 3;
}
int main()
{
//創建信號量
hsem1 = CreateSemaphore(NULL, 1, 1, NULL);
hsem2 = CreateSemaphore(NULL, 0, 1, NULL);
hsem3 = CreateSemaphore(NULL, 0, 1, NULL);
HANDLE hth1, hth2, hth3;
//創建線程
hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);
hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);
hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL);
//等待子線程結束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE);
//一定要記得關閉線程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3);
CloseHandle(hsem1);
CloseHandle(hsem2);
CloseHandle(hsem3);
}
信號量沒有線程所有權屬性,即一個線程獲得某個信號量后,在他釋放該信號量之前,他不能再次進入信號量保護的區域
【版權聲明】轉載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3601252.html
