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!
下面的博文我将介绍其他几种线程同步的方法。