标签: 信号量api函数win32downit |
分类: 多线程编程 |
一、关于信号量
1、在信号量中有一个内置的计数值,用于对资源进行计数;同时它通过内置的互斥机制保证在有多个线程试图对计数值进行修改时,在任一时刻只有一个线程对计数值进行修改。
2、信号量的两个核心操作是Up操作(提高计数值)和Down操作(降低计数值):
1)Down操作:
检查信号量的计数值是否大于零
1》若大于零,信号量的计数值减一(即用掉了一个信号量计数了),线程继续运行;
2》若等于零(也就是线程不能获得所需的信号量了),于是进入睡眠状态。
Down操作的原子性保证了一旦一个线程对信号量的
操作开始,其他线程就不能访问,知道操作完成或阻塞。
2)Up操作
用于线程释放对信号量的所有权,提高信号量的计数值。
若有多个线程正睡眠在该信号量上,则其中一个被操作系统选中,并被允许调用Down操作,此时计数值仍为零。于是睡眠在该信号量上的少了一个。
二、有关函数
CreateSemaphore() 创建一个信号量
OpenSemaphore() 打开一个已经创建的信号量
ReleaseSemaphore() 释放对信号量的所有权
三、用法
#include
#include
#include
HANDLE hSemaphore;
DWORD WINAPI MyThread(LPVOID lpParameter)
{
int *pNo=(int*)lpParameter;
WaitForSingleObject(hSemaphore,INFINITE);//等待信号量
cout<<"Thread# "<<*pNo<<"get the Semaphore"<
cout<<"Thread# "<<*pNo<<"release Semaphore"<
return 1;
}
int main(int argc,char *argv[])
{
int ThNo[6];
DWORD dw;
hSemaphore = CreateSemaphore(NULL,3,3,NULL);//创建信号量 ,最大计数值为3
for(int i=0;i<6;i++)
{
ThNo[i]=i+1;
CreateThread(NULL,0,MyThread,&ThNo[i],NULL,&dw);//创建线程
}
Sleep(6000);//6000毫秒后结束进程
return 0;
}
这个程序因为利用了Sleep(),让我们明显的观测到信号量的获得和释放。
1、主线程创建了一个信号量,每次只允许3个线程同时获得信号量,于是线程1,2,3获得信号量,其余三个处于睡眠状态。
2、1000毫秒之后,线程1释放信号量,线程4获得
3、2000毫秒之后,线程2释放信号量,线程5获得
4、3000毫秒之后,线程3释放信号量,线程6获得
5、最后6000毫秒的时间到,线程4,5,6分别释放信号量。程序结果运行如下。
由于竞争的关系,抢到信号量的线程是随机的,所以会出现不一定按1,2,3顺序输出的情况。
从这可以清楚的看到,只有释放了一个线程,才能再获得一个,总之就是在同一个时刻里只能有三个线程能拥有该信号量。