windows多线程没那么难

windows多线程没那么难

作者:vpoet
mail:vpoet_sir@163.com

上一博文中我们引入了CreateThread()多线程编程一个简单的例子,事实上我说windows
多线程没那么难,那是为了安慰你,但是不要怕,困难时让人克服的。再大的困难也难不
倒英雄的中国程序员。

下面我又要介绍一个多线程的问题:
我们首先看一个Demo,经典的卖票问题,同一张牌不能卖出去两次:
 1 #include <windows.h>
 2 #include <stdio.h>
 3 
 4 static int number=20;
 5 
 6 DWORD WINAPI ThreadOne(LPVOID lpParameter)
 7 {
 8     while(1)
 9     {
10         if(number>0)
11         {
12             printf("窗口1售出第%d张票...\n",number);
13             Sleep(1000);
14             number--;
15         }
16     }
17     return 0;
18 }
19 DWORD WINAPI ThreadTwo(LPVOID lpParameter)
20 {
21     while(1)
22     {
23         if(number>0)
24         {
25             printf("窗口2售出第%d张票...\n",number);
26             Sleep(1000);
27             number--;
28         }
29     }
30     return 0;
31 }
32 
33 
34 int main()
35 {
36     HANDLE HOne,HTwo;
37     printf("***********************vpoet******************\n");
38     HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
39     printf("窗口1售票开始:\n");
40     HTwo=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);
41     printf("窗口2售票开始:\n");
42     CloseHandle(HOne);
43     CloseHandle(HTwo);
44     while(TRUE)
45     {
46         if(number==0)
47         {
48             printf("MainThread Over!\n");
49             return 0;
50         }
51         else
52         {
53             continue;
54         }    
55     }
56 
57     return 0;
58 }

 

运行结果:


 
看到没,出现了同一张票卖两次的情况,这是绝对错误的,是违反能量守恒定律的。
这是为什么呢,因为我们对全局变量操作两个线程在同时进行,如果在窗口1线程的number++
之前,窗口2线程取出了number这时的number还并未自加,所以出现了同一张票
卖两次的情况

那么我们就要用线程同步的方法来控制,怎么控制呢,在windows下控制
多线程同步一般有几种方法:临界区对象,事件对象和互斥对象以及锁
下面主要介绍临界区对象进行线程同步:



在win API中:


该函数为初始化临界区函数,参数为临界区对象




该函数等待指定的临界区对象的所有权,当获取指定的临界区对象的所有权之后该函数返回
其参数为临界区对象指针



该函数释放指定临界区对象的所有权,参数为临界区对象指针




该函数为删除释放临界区对象资源






那么接下来我们将用临界区对程序进行改写:
 1 #include <windows.h>
 2 #include <stdio.h>
 3 
 4 static int number=10;
 5 CRITICAL_SECTION Section;
 6 
 7 DWORD WINAPI ThreadOne(LPVOID lpParameter)
 8 {
 9     while(1)
10     {
11         EnterCriticalSection(&Section);
12         if(number>0)
13         {
14             printf("窗口1售出第%d张票...\n",number);
15             number--;
16             Sleep(1000);        
17         }
18         LeaveCriticalSection(&Section);
19     }
20     return 0;
21 }
22 DWORD WINAPI ThreadTwo(LPVOID lpParameter)
23 {
24     while(1)
25     {
26         EnterCriticalSection(&Section);
27         if(number>0)
28         {
29             printf("窗口2售出第%d张票...\n",number);
30             Sleep(1000);
31             number--;
32         }
33         LeaveCriticalSection(&Section);
34     }
35     return 0;
36 }
37 
38 
39 int main()
40 {
41     HANDLE HOne,HTwo;
42     InitializeCriticalSection(&Section);
43     printf("***********************vpoet******************\n");
44     HOne=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);
45     printf("窗口1售票开始:\n");
46     HTwo=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);
47     printf("窗口2售票开始:\n");
48     CloseHandle(HOne);
49     CloseHandle(HTwo);
50     while(TRUE)
51     {
52         if(number==0)
53         {
54             printf("不好意思,票卖完了!\n");
55             DeleteCriticalSection(&Section);
56             return 0;
57         }
58         else
59         {
60             continue;
61         }    
62     }
63 
64     return 0;
65 }
运行结果如下:

这下票卖对了吧。

好了,Only stop here!
下面的博文我将介绍其他几种线程同步的方法。

 

转载于:https://www.cnblogs.com/vpoet/p/4659575.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值