信号量和事件内核对象一样,不会记录当前拥有资源的线程ID,没有线程占有权一说,信号量靠资源数量来进行同步,可用资源量等于0,代表信号量未激活,大于0,信号量被激活,并且允许资源数量个线程进入。
#include <iostream> #include <process.h> #include <windows.h> #include <string> using std::cout; using std::endl; using std::string; const int num=2; int count; HANDLE _Semaphore; unsigned __stdcall ThreadFun(void* par); int main() { count=0; HANDLE handles[num]; //创建一个初始资源0,最大并发1的信号量 _Semaphore=CreateSemaphore(NULL,0,1,NULL); for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); //等待信号量可用资源数大于0(资源数大于0表示信号量处于触发状态) WaitForSingleObject(_Semaphore,INFINITE); } //等待所有线程执行完毕 WaitForMultipleObjects(num,handles,TRUE,INFINITE); for(int i=0;i<num;++i) CloseHandle(handles[i]); //关系信号量 CloseHandle(_Semaphore); system("PAUSE"); return 0; } unsigned __stdcall ThreadFun(void* par) { for(int i=0;i<10;++i) cout<<"cout:"<<++count<<endl; count=0; //释放一个资源,让信号量的资源数加1(注意:这里输出可能乱,只是为了观察ReleaseSemaphore结果) cout<<"ReleaseSemaphore:"<<ReleaseSemaphore(_Semaphore,1,NULL)<<endl; return 0; }
如果我们将代码修改一下,一共有3个线程,并且信号量资源最大数为3,ReleaseSemaphore(_Semaphore,2,NULL)每次释放递增2个可用资源,那么结果就会不一样,第一个线程输出正常,然后递增2个可用资源,剩下2个线程就可以顺利执行,导致后面2个线程无法同步。
#include <iostream> #include <process.h> #include <windows.h> #include <string> using std::cout; using std::endl; using std::string; const int num=3; int count; HANDLE _Semaphore; unsigned __stdcall ThreadFun(void* par); int main() { count=0; HANDLE handles[num]; //创建一个初始资源0,最大并发1的信号量 _Semaphore=CreateSemaphore(NULL,0,3,NULL); for(int i=0;i<num;++i) { handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0); //等待信号量可用资源数大于0(资源数大于0表示信号量处于触发状态) WaitForSingleObject(_Semaphore,INFINITE); } //等待所有线程执行完毕 WaitForMultipleObjects(num,handles,TRUE,INFINITE); for(int i=0;i<num;++i) CloseHandle(handles[i]); //关系信号量 CloseHandle(_Semaphore); system("PAUSE"); return 0; } unsigned __stdcall ThreadFun(void* par) { for(int i=0;i<10;++i) cout<<"cout:"<<++count<<endl; count=0; //释放一个资源,让信号量的资源数加1(注意:这里输出可能乱,只是为了观察ReleaseSemaphore结果) cout<<"ReleaseSemaphore:"<<ReleaseSemaphore(_Semaphore,2,NULL)<<endl; return 0; }
注意输出结果,后面2个线程同步失败
本文版权归kennyMc和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。