标签:
注:本文写得十分简略.如感到难以理解,请立即参考另一篇写得比我好得多的文章
我们先看一个示例
1 #include <windows.h> 2 #include <stdio.h> 3 4 DWORD WINAPI reportFunc(LPVOID); // 线程函数的一般原型.可以不返回任何值 5 6 #define CntMsg 100 7 8 int main() 9 { 10 /* 建立一个新线程并令其立即执行,返回这个线程的handle 11 * 第三个参数reportFunc代表这个新线程所调用的函数,不同线程可以调用同一个函数 12 * 第四个参数NULL代表传给reportFunc的参数(建议使用指针).传参时会转成void指针,由接收方再转成需要的类型.将会在下个示例程序中用到 13 * 第五个参数0代表立即执行此线程 14 */ 15 HANDLE reportHandle = CreateThread(NULL, 0, reportFunc, NULL, 0, NULL); 16 CloseHandle(reportHandle); // 礼节性调用.可有可无 17 18 for (int i = 0; i < CntMsg; ++i) printf("Main Thread: %d\n", i); 19 20 Sleep(1000); // 如果不加这一句,可能会造成主线程报完数并退出后子线程尚未报完数的情况 21 } 22 23 DWORD WINAPI reportFunc(LPVOID para) 24 { 25 for (int i = 0; i < CntMsg; ++i) printf("Report Thread: %d\n", i); 26 }
它的输出大概是这样的(不知道是因为什么,我前两次测试的结果都很奇怪:主线程报完数后子线程才开始报数.这是我第三次测试的结果)
Main Thread: 0 Main Thread: 1 Main Thread: 2 Main Thread: 3 Main Thread: 4 Main Thread: 5 Main Thread: 6 Main Thread: 7 Main Thread: 8 Main Thread: 9 Main Thread: 10 Main Thread: 11 Main Thread: 12 Main Thread: 13 Main Thread: 14 Main Thread: 15 Main Thread: 16 Main Thread: 17 Main Thread: 18 Main Thread: 19 Main Thread: 20 Main Thread: 21 Main Thread: 22 Main Thread: 23 Main Thread: 24 Main Thread: 25 Main Thread: 26 Main Thread: 27 Main Thread: 28 Main Thread: 29 Main Thread: 30 Main Thread: 31 Main Thread: 32 Main Thread: 33 Main Thread: 34 Main Thread: 35 Main Thread: 36 Main Thread: 37 Main Thread: 38 Main Thread: 39 Main Thread: 40 Main Thread: 41 Main Thread: 42 Main Thread: 43 Main Thread: 44 Main Thread: 45 Main Thread: 46 Main Thread: 47 Main Thread: 48 Main Thread: 49 Main Thread: 50 Main Thread: 51 Main Thread: 52 Main Thread: 53 Report Thread: 0 Report Thread: 1 Report Thread: 2 Report Thread: 3 Report Thread: 4 Report Thread: 5 Report Thread: 6 Report Thread: 7 Report Thread: 8 Report Thread: 9 Report Thread: 10 Report Thread: 11 Report Thread: 12 Report Thread: 13 Report Thread: 14 Report Thread: 15 Report Thread: 16 Report Thread: 17 Report Thread: 18 Report Thread: 19 Report Thread: 20 Report Thread: 21 Report Thread: 22 Report Thread: 23 Report Thread: 24 Report Thread: 25 Report Thread: 26 Report Thread: 27 Report Thread: 28 Report Thread: 29 Report Thread: 30 Report Thread: 31 Report Thread: 32 Report Thread: 33 Report Thread: 34 Report Thread: 35 Report Thread: 36 Report Thread: 37 Report Thread: 38 Report Thread: 39 Report Thread: 40 Report Thread: 41 Report Thread: 42 Report Thread: 43 Report Thread: 44 Report Thread: 45 Report Thread: 46 Report Thread: 47 Report Thread: 48 Main Thread: 54 Main Thread: 55 Main Thread: 56 Main Thread: 57 Main Thread: 58 Main Thread: 59 Main Thread: 60 Main Thread: 61 Main Thread: 62 Main Thread: 63 Main Thread: 64 Main Thread: 65 Main Thread: 66 Main Thread: 67 Main Thread: 68 Main Thread: 69 Main Thread: 70 Main Thread: 71 Main Thread: 72 Main Thread: 73 Main Thread: 74 Main Thread: 75 Main Thread: 76 Main Thread: 77 Main Thread: 78 Main Thread: 79 Main Thread: 80 Main Thread: 81 Main Thread: 82 Main Thread: 83 Main Thread: 84 Main Thread: 85 Main Thread: 86 Main Thread: 87 Main Thread: 88 Main Thread: 89 Main Thread: 90 Main Thread: 91 Main Thread: 92 Main Thread: 93 Main Thread: 94 Main Thread: 95 Main Thread: 96 Main Thread: 97 Main Thread: 98 Main Thread: 99 Report Thread: 49 Report Thread: 50 Report Thread: 51 Report Thread: 52 Report Thread: 53 Report Thread: 54 Report Thread: 55 Report Thread: 56 Report Thread: 57 Report Thread: 58 Report Thread: 59 Report Thread: 60 Report Thread: 61 Report Thread: 62 Report Thread: 63 Report Thread: 64 Report Thread: 65 Report Thread: 66 Report Thread: 67 Report Thread: 68 Report Thread: 69 Report Thread: 70 Report Thread: 71 Report Thread: 72 Report Thread: 73 Report Thread: 74 Report Thread: 75 Report Thread: 76 Report Thread: 77 Report Thread: 78 Report Thread: 79 Report Thread: 80 Report Thread: 81 Report Thread: 82 Report Thread: 83 Report Thread: 84 Report Thread: 85 Report Thread: 86 Report Thread: 87 Report Thread: 88 Report Thread: 89 Report Thread: 90 Report Thread: 91 Report Thread: 92 Report Thread: 93 Report Thread: 94 Report Thread: 95 Report Thread: 96 Report Thread: 97 Report Thread: 98 Report Thread: 99
这个程序的功能是建立一个新线程,令其与主线程一起报数
几个线程同时访问同一个变量时,可能会出现一些问题.为了解决这个问题,有人发明了Mutex.这是一个标志,用于判断某个东东是否无法在现在访问(即现在正在被其它线程访问)
下面我们看看第二个示例程序
1 #include <windows.h> 2 #include <stdio.h> 3 4 int tickets = 100; // 票量 5 HANDLE ticketMutex; // Mutex的类型是HANDLE 6 7 DWORD WINAPI trainStation(LPVOID para) 8 { 9 char* stationName = para; // 转类型,接收车站名信息 10 11 while (1) 12 { 13 // 等待Mutex被其它线程释放后,锁定Mutex 14 // 锁定Mutex,相当于告诉其它线程要等待它调用ReleaseMutex后,才能对tickets变量进行操作 15 WaitForSingleObject(ticketMutex, INFINITE); 16 17 if (tickets <= 0) break; 18 printf("%s> %d\n", stationName, --tickets); // 抢票 19 20 // 释放Mutex,告诉其它线程可以开始对tickets变量进行操作了 21 ReleaseMutex(ticketMutex); 22 } 23 } 24 25 #define ARRSIZ(arr) (sizeof(arr) / sizeof(arr[0])) 26 27 int main() 28 { 29 // 使用CreateMutex函数来建立一个Mutex 30 // 其中,最后一个(第三个)参数是一个标识符 31 // 假如需要判断此Mutex是否已被创建,可以写类似CreateMutex(NULL, FALSE, "tickets")之类的代码 32 // 如果另一个标识符为"tickets"的Mutex已被创建,那么ERROR_ALREADY_EXISTS == GetLastError() 33 ticketMutex = CreateMutex(NULL, FALSE, NULL); 34 35 // 车站名 36 char stations[][20] = 37 { 38 "GuangZhou", "BeiJing", "ShangHai", 39 "HuNan", "HeiLongJiang", "XinJiang", 40 }; 41 42 // 依次创建代表各省车站的子线程 43 for (int i = 0; i < ARRSIZ(stations); ++i) 44 { 45 CloseHandle(CreateThread(NULL, 0, trainStation, stations[i], 0, NULL)); 46 } 47 48 while (1) 49 { 50 WaitForSingleObject(ticketMutex, INFINITE); // 同上 51 if (tickets <= 0) break; // 假如票卖完了,退出程序 52 ReleaseMutex(ticketMutex); // 同上 53 } 54 }
它的输出大概是这样的
GuangZhou> 99 GuangZhou> 98 GuangZhou> 97 GuangZhou> 96 GuangZhou> 95 ShangHai> 94 GuangZhou> 93 ShangHai> 92 GuangZhou> 91 HeiLongJiang> 90 HuNan> 89 ShangHai> 88 BeiJing> 87 XinJiang> 86 GuangZhou> 85 HeiLongJiang> 84 HuNan> 83 ShangHai> 82 BeiJing> 81 XinJiang> 80 GuangZhou> 79 HeiLongJiang> 78 HuNan> 77 ShangHai> 76 BeiJing> 75 XinJiang> 74 GuangZhou> 73 HeiLongJiang> 72 HuNan> 71 ShangHai> 70 BeiJing> 69 XinJiang> 68 GuangZhou> 67 HeiLongJiang> 66 HuNan> 65 ShangHai> 64 BeiJing> 63 XinJiang> 62 GuangZhou> 61 HeiLongJiang> 60 HuNan> 59 ShangHai> 58 BeiJing> 57 XinJiang> 56 GuangZhou> 55 HeiLongJiang> 54 HuNan> 53 ShangHai> 52 BeiJing> 51 XinJiang> 50 GuangZhou> 49 HeiLongJiang> 48 HuNan> 47 ShangHai> 46 BeiJing> 45 XinJiang> 44 GuangZhou> 43 HeiLongJiang> 42 HuNan> 41 ShangHai> 40 BeiJing> 39 XinJiang> 38 GuangZhou> 37 HeiLongJiang> 36 HuNan> 35 ShangHai> 34 BeiJing> 33 XinJiang> 32 GuangZhou> 31 HeiLongJiang> 30 HuNan> 29 ShangHai> 28 BeiJing> 27 XinJiang> 26 GuangZhou> 25 HeiLongJiang> 24 HuNan> 23 ShangHai> 22 BeiJing> 21 XinJiang> 20 GuangZhou> 19 HeiLongJiang> 18 HuNan> 17 ShangHai> 16 BeiJing> 15 XinJiang> 14 GuangZhou> 13 HeiLongJiang> 12 HuNan> 11 ShangHai> 10 BeiJing> 9 XinJiang> 8 GuangZhou> 7 HeiLongJiang> 6 HuNan> 5 ShangHai> 4 BeiJing> 3 XinJiang> 2 GuangZhou> 1 HeiLongJiang> 0
这个程序的功能是模拟火车站的售票系统.各个次线程模拟各个省的火车站,互相竞争100张票,抢到票后输出省份的名称以及剩余的票量.主线程监视票量,在票卖完后停止程序
注意一点:Mutex本身并不知道自己负责管理哪个变量,是否对变量进行操作是完全由程序员来进行的.也就是说,假如某一火车站急需车票,它可以无视Mutex,进行暴力抢票.假如它运气不好,碰上几个线程同时访问同一个变量,就会出现票量异常等情况.假如它运气好,那就当什么事都没有发生,多拿了几张票罢了
你也可以用一个Mutex来完成对多个变量的管理,依个人喜好而定
WinApi多线程(CreateThread,CreateMutex,ReleaseMutex)
标签:
原文地址:http://www.cnblogs.com/yanh2001/p/winApiThread20150516.html