题目要求:
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推
分析:
本问题为线程同步问题。申请三个事件对象保持三个线程同步(先子线程A,再线程B,然后线程C)!
显然事件对象很适合做。
SetEvent(),将事件对象设置为有信号
ResetEvent(),将事件对象设置为无信号
WaitForSingleObject(),有信号才能被申请。
a)子线程A先执行,则子线程A的事件对象必须有信号,而其他线程必须先无信号(等待线程A执行完后开启)!
b)子线程A执行完一次后,则将子线程A事件对象无信号,将线程B事件对象设置为有信号
c)线程B执行完一次后,则将线程B事件对象无信号,将子线程C事件对象有信号(准备被申请并执行子线程C)
d)如此往复10次上诉行为。
具体代码如下:
#include <process.h> #include <windows.h> #include <stdio.h> unsigned int __stdcall Fun(void *pPM); //线程个数 const int THREAD_NUM = 3; //循环次数 const int LOOP = 10; //互斥事件 HANDLE g_hThreadEvent[THREAD_NUM]; int main() { // TODO: Place code here. HANDLE hdl[THREAD_NUM]; for (int i = 0; i < THREAD_NUM; i++) { g_hThreadEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL); } //将线程编号作为线程参数传进去,先转换为指针,再转换为整形 for (i = 0; i < THREAD_NUM; i++) hdl[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, (int*)i, 0, NULL); SetEvent(g_hThreadEvent[0]);//线程0,触发为有信号,可以执行了 Sleep(1000); //让线程进入等待状态,保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, hdl, TRUE, INFINITE); for (i = 0; i < THREAD_NUM; i++) { CloseHandle(hdl[i]); CloseHandle(g_hThreadEvent[i]); } getchar(); return 0; } unsigned int __stdcall Fun(void *pPM) { int num = (int )pPM; for (int i = 0; i< LOOP; i++)//10 { WaitForSingleObject(g_hThreadEvent[num], INFINITE);//等待g_hThreadEvent[num]有信号,若无将一直等待 ResetEvent(g_hThreadEvent[num]); printf("%c", 'A'+ num); SetEvent(g_hThreadEvent[(num + 1) % THREAD_NUM]);//将下一个线程设置为有信号 } return 0; }
VC6.0下面的运行结果:
这一段代码如果将_beginthreadex()换成CreateThread()没问题,但是要用_beginthreadex()的话就会出错!!!
运行之后会出现错误_beginthreadex()没有定义。这时候需要你改变设置。
_beginthreadex不仅要加头文件“process.h”还要设置工程属性;
在VC6下用_beginthreadex编写多线程程序时,不但要将<process.h>包含进来,而且还是设置工程属性,选择"C/C++"一栏,在分类里选择Code Generation,在Use run-time library那一个栏选择多线程版本(带有Multithreaded的)就可以了。