windows多线程同步--临界区

windows多线程同步--临界区

推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS

 

关于临界区的观念,一般操作系统书上面都有。

适用范围:它只能同步一个进程中的线程,不能跨进程同步。一般用它来做单个进程内的代码快同步,效率比较高

windows中与临界区有关的结构是 CRITICAL_SECTION,关于该结构体的内部结构可参考here

使用时,主线程中要先初始化临界区,最后要删除临界区,具体使用见下面代码:

                                                                              本文地址

从一个例子来说明:假设有三个线程都需要使用打印机,我们可以把打印的代码放到临界区,这样就可以保证每次只有一个线程在使用打印机。

 

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

#include<string>

 #include<iostream>

 #include<process.h>

 #include<windows.h>

 using namespace std;

 

 //定义一个临界区

 CRITICAL_SECTION g_cs;

 

//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall

unsigned __stdcall threadFun(void *param)

{

    EnterCriticalSection(&g_cs);//进入临界区,如果有其他线程则等待

    cout<<*(string *)(param)<<endl;

    LeaveCriticalSection(&g_cs);//退出临界区,其他线程可以进来了

    return 1;

}

 

 

int main()

{

    //初始化临界区

    InitializeCriticalSection(&g_cs);

 

    HANDLE hth1, hth2, hth3;

    string s1 = "first", s2 = "second", s3 = "third";

 

    //创建线程

    hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s1, 0, NULL);

    hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s2, 0, NULL);

    hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s3, 0, NULL);

 

    //等待子线程结束

    WaitForSingleObject(hth1, INFINITE);

    WaitForSingleObject(hth2, INFINITE);

    WaitForSingleObject(hth3, INFINITE);

 

    //一定要记得关闭线程句柄

    CloseHandle(hth1);

    CloseHandle(hth2);

    CloseHandle(hth3);

 

    //删除临界区

    DeleteCriticalSection(&g_cs);

}

 

再看另外一个问题:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推, 仿照文章windows多线程同步--信号量中的代码,我们把信号量替换成临界区。

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

65

66

67

#include<string>

 #include<iostream>

 #include<process.h>

 #include<windows.h>

 using namespace std;

 //声明3个临界区

CRITICAL_SECTION  g_cs1, g_cs2, g_cs3;

 

//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall

unsigned __stdcall threadFunA(void *)

{

    for(int i = 0; i < 10; i++){

        EnterCriticalSection(&g_cs1);//进入临界区

        cout<<"A";

        LeaveCriticalSection(&g_cs2);//离开临界区

    }

    return 1;

}

unsigned __stdcall threadFunB(void *)

{

    for(int i = 0; i < 10; i++){

        EnterCriticalSection(&g_cs2);//进入临界区

        cout<<"B";

        LeaveCriticalSection(&g_cs3);//离开临界区

    }

    return 2;

}

unsigned __stdcall threadFunC(void *)

{

    for(int i = 0; i < 10; i++){

        EnterCriticalSection(&g_cs3);//进入临界区

        cout<<"C";

        LeaveCriticalSection(&g_cs1);//离开临界区

    }

    return 3;

}

 

 

int main()

{

    //初始化临界区

    InitializeCriticalSection(&g_cs1);

    InitializeCriticalSection(&g_cs2);

    InitializeCriticalSection(&g_cs3);

 

    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);

 

    //删除临界区

    DeleteCriticalSection(&g_cs1);

    DeleteCriticalSection(&g_cs2);

    DeleteCriticalSection(&g_cs3);

}

 

image

为什么会这样呢,因为临界区有所有权的概念,即某个线程进入临界区后,就拥有该临界区的所有权,在他离开临界区之前,他可以无限次的再次进入该临界区,上例中线程A获得临界区1的所有权后,在线程C调用LeaveCriticalSection(&g_cs1)之前,A是可以无限次的进入临界区1的。利用信号量之所以可以实现题目的要求,是因为信号量没有所有权的概念,某个线程获得信号量后,如果信号量的值为0,那么他一定要等到信号量被释放时,才能再次获得

关于临界区的详细解释清参考秒杀多线程第五篇 经典线程同步 关键段CS

 

【版权声明】转载请注明出处http://www.cnblogs.com/TenosDoIt/p/3601308.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值