c++多线程实现循环打印ABC

来源:互联网 发布:spss分析数据的步骤 编辑:程序博客网 时间:2024/05/17 07:36

网上的资料基本都是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-CHANDLE 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;}
阅读全文
0 0
原创粉丝点击