网上的资料基本都是java实现的,c++的很少,加上win32的API函数对我个人而言晦涩难懂,真是举步维艰~
目前而言对我来说最好理解的,最简单的,是使用Event。
首先明白Event的用法:秒杀多线程第六篇 经典线程同步 事件Event
CreateEvent
函数功能:创建事件
//函数原型:
HANDLECreateEvent( LPSECURITY_ATTRIBUTESlpEventAttributes, BOOLbManualReset, BOOLbInitialState, LPCTSTRlpName );
函数说明:
- 第一个参数表示安全控制,一般直接传入NULL。
- 第二个参数确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。打个小小比方,手动置位事件相当于教室门,教室门一旦打开(被触发),所以有人都可以进入直到老师去关上教室门(事件变成未触发)。自动置位事件就相当于医院里拍X光的房间门,门打开后只能进入一个人,这个人进去后会将门关上,其它人不能进入除非门重新被打开(事件重新被触发)。
(此中有坑)- 第三个参数表示事件的初始状态,传入TRUR表示已触发。
- 第四个参数表示事件的名称,传入NULL表示匿名事件。
SetEvent
函数功能:触发事件
函数原型:BOOLSetEvent(HANDLEhEvent);
函数说明:每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态。
ResetEvent
函数功能:将事件设为末触发
函数原型:BOOLResetEvent(HANDLEhEvent);
最简单的实现是,先分别创建三个线程分别打印对应次数的字母A/B/C,还有三个事件event ,其中每个线程在打印的时候使用waitforsingleobject来阻塞,只有wait到了对应的事件,才可以输出对应的字母,然后打印完毕后,用setevent把下一个事件触发,然后执行下一个事件。
最简单的代码:
using namespace std;
const int NUM = 3;
int nCount = 1; //用来表示先打印哪一个 0-A,1-B,2-C
HANDLE g_Event[NUM] = { NULL };//三个事件
unsigned int WINAPI funA(LPVOID pM)
{
for (int i = 0; i < 100; i++)
{
WaitForSingleObject(g_Event[0], INFINITE); //等待g_Event[0],然后才执行打印A;
cout << 'A';
Sleep(100);
nCount ++ ;
SetEvent(g_Event[(nCount) % NUM]);
}
return 0;
}
unsigned int WINAPI funB(LPVOID pM)
{
for (int i = 0; i < 100; i++)
{
WaitForSingleObject(g_Event[1], INFINITE);
cout << 'B';
Sleep(100);
nCount++;
SetEvent(g_Event[(nCount) % NUM]);
}
return 0;
}
unsigned int WINAPI funC(LPVOID pM)
{
for (int i = 0; i < 100; i++)
{
WaitForSingleObject(g_Event[2], INFINITE);
cout << 'C';
Sleep(100);
nCount++;
SetEvent(g_Event[(nCount) % NUM]);
}
return 0;
}
int main()
{
HANDLE threads[NUM] = { NULL };
for (unsigned int i = 0; i < 3; i++)
{
g_Event[i] = CreateEvent(NULL, FALSE, FALSE, NULL); //这里的第二个参数是False,意思是这个事件执行完后,会自动设置为未触发状态(形参3的参数就是设置默认是否为触发),如果是TRUE,则需要执行完后手动置为未触发,用ResetEvent函数即可。
}
threads[0] = (HANDLE)_beginthreadex(NULL, 0, funA, NULL, 0, NULL);
threads[1] = (HANDLE)_beginthreadex(NULL, 0, funB, NULL, 0, NULL);
threads[2] = (HANDLE)_beginthreadex(NULL, 0, funC, NULL, 0, NULL);
SetEvent(g_Event[nCount]);
WaitForMultipleObjects(NUM, threads, TRUE, INFINITE);
CloseHandle(g_Event[0]);
CloseHandle(g_Event[1]);
CloseHandle(g_Event[2]);
memset(g_Event, 0, sizeof(HANDLE)*NUM);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(threads[2]);
memset(threads, 0, sizeof(HANDLE)*NUM);
return 0;
}
写的太复杂了,还用了EVENT数组,简直是没有困难创造困难。
下面的这个代码就很好理解。
http://blog.csdn.net/bupt8846/article/details/45541723
#include <stdio.h>
#include <windows.h>
#include<iostream>
#include <process.h>
#include <time.h>
using namespace std;
HANDLE g_a, g_b, g_c;
CRITICAL_SECTION g_cs;
unsigned int __stdcall PrintA(void* pM)
{
int i = 0;
while (i < 10)
{
WaitForSingleObject(g_a, INFINITE);
//EnterCriticalSection(&g_cs);
cout <<i+1<< ": A";
++i;
SetEvent(g_b);
//LeaveCriticalSection(&g_cs);
}
return 0;
}
unsigned int __stdcall PrintB(void* pM)
{
int i = 0;
while (i < 10)
{
WaitForSingleObject(g_b, INFINITE);
//EnterCriticalSection(&g_cs);
cout << 'B';
++i;
SetEvent(g_c);
//LeaveCriticalSection(&g_cs);
}
return 0;
}
unsigned int __stdcall PrintC(void* pM)
{
int i = 0;
while (i < 10)
{
WaitForSingleObject(g_c, INFINITE);
//EnterCriticalSection(&g_cs);
cout << "C\n";
++i;
SetEvent(g_a);
//LeaveCriticalSection(&g_cs);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
InitializeCriticalSection(&g_cs);
g_a = CreateEvent(NULL, FALSE, TRUE, NULL); //这里设置为TRUE,默认g_a是触发的。
g_b = CreateEvent(NULL, FALSE, FALSE, NULL);
g_c = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE threads[3];
threads[0] = (HANDLE)_beginthreadex(NULL, 0, PrintA, NULL, 0, NULL);
threads[1] = (HANDLE)_beginthreadex(NULL, 0, PrintB, NULL, 0, NULL);
threads[2] = (HANDLE)_beginthreadex(NULL, 0, PrintC, NULL, 0, NULL);
WaitForMultipleObjects(3, threads, TRUE, INFINITE);
CloseHandle(g_a);
CloseHandle(g_b);
CloseHandle(g_c);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(threads[2]);
DeleteCriticalSection(&g_cs);
cout << endl;
system("pause");
return 0;
}
简单的版本,避免代码重复太多。
using namespace std;
const int NUM = 3;
int nCount = 1;
HANDLE g_Event[NUM] = { NULL };
//HANDLE g_Mutex = NULL ;
unsigned int WINAPI fun(LPVOID pM)
{
int nParam = (int)pM;
char res = 'A' + nParam;
for (int i = 0; i < 100; i++)
{
WaitForSingleObject(g_Event[nParam], INFINITE);
cout << res;
Sleep(100);
ResetEvent(g_Event[nParam]);
SetEvent(g_Event[(nParam + 1) % NUM]); //触发下一个事件
}
return 0;
}
int main()
{
HANDLE threads[NUM] = { NULL };
for (unsigned int i = 0; i < 3; i++)
{
g_Event[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
threads[i] = (HANDLE)_beginthreadex(NULL, 0, fun, (void *)i, 0, NULL);
}
SetEvent(g_Event[nCount]);
WaitForMultipleObjects(NUM, threads, TRUE, INFINITE);
CloseHandle(g_Event[0]);
CloseHandle(g_Event[1]);
CloseHandle(g_Event[2]);
memset(g_Event, 0, sizeof(HANDLE)*NUM);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(threads[2]);
memset(threads, 0, sizeof(HANDLE)*NUM);
return 0;
}