windows多线程同步--信号量

首先先介绍和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的信号量。具体见下面代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#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);
}

 

信号量没有线程所有权属性,即一个线程获得某个信号量后,在他释放该信号量之前,他不能再次进入信号量保护的区域






本文转自tenos博客园博客,原文链接:http://www.cnblogs.com/TenosDoIt/p/3601252.html,如需转载请自行联系原作者

上一篇:分析HTTP请求以降低HTTP走私攻击HTTP数据接收不同步攻击的风险


下一篇:android调用系统拍照程序和从图库选取图片,返回后调用系统裁剪工具