天天看點

windows C++ 互相等待線程同步示例

windows C++ 互相等待線程同步示例

開發中遇到線程同步問題,可抽象為如下模型:

1、主線程的繼續執行的前提是子線程的變量已經初始化完畢。

2、子線程待主線程執行完畢後繼續執行後續的初始化操作。

重複1,2執行……直到通信結束。

如下圖所示:

windows C++ 互相等待線程同步示例
源碼(VS2010編譯、運作通過)

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <windows.h>
const char* g_pszEventName = "GLOBAL/MY_EVENT";  //事件對象的名稱
HANDLE g_hSetTaskIdEvent = NULL;                 //全局Event事件

const int g_iMaxRunCnt = 50;                     //最大的運作次數.
/*
**@brief:模拟線程函數。
**@param:LPVOID pParam 線程參數,未使用(可傳遞結構體指針等)
**@return 0,ok; 其他代表異常退出。
*/
UINT RecvDataThreadProc(LPVOID pParam)
{
 cout << "The RecvDataThreadProc() is Running!" << endl;
 int nThreadCnt = 0;
 while(nThreadCnt < g_iMaxRunCnt)
 {
  printf("[Thread] The TaskId already Setted! RunCnt = %d\n", nThreadCnt++);
  SetEvent(g_hSetTaskIdEvent); //觸發,主線程可以運作.
  WaitForSingleObject(g_hSetTaskIdEvent, INFINITE);
 }
 return 0;
}
/*
**@brief:主線程和副線程交替運作。
**
**
*/
int _tmain(int argc, _TCHAR* argv[])
{
 // 啟動一個處理線程
 DWORD dwThreadId = 0;
 HANDLE hRecvThread = CreateThread(NULL, //Choose default security
           0,                             //Default stack size
             (LPTHREAD_START_ROUTINE)&RecvDataThreadProc,//Routine to execute
             (LPVOID) NULL,                              //Thread parameter
              0,                                         //Immediately run the thread
             &dwThreadId                                //Thread Id
             );
 if (NULL == hRecvThread)
 {
  printf("CreateThread Failed! ErrCode: %d\n", GetLastError());
  return(1);
 }
 else
 {
  printf("CreateThread OK!\n");
 }
 CloseHandle(hRecvThread);
 //1.建立命名的事件對象,自動且初始化為無信号狀态
 g_hSetTaskIdEvent= CreateEvent(NULL, FALSE, FALSE, (LPCWSTR)(g_pszEventName)); 
 int iErrorCode = GetLastError();
 if (ERROR_ALREADY_EXISTS == iErrorCode)
 {
  printf("[Process]CreateEvent() the object is already exist!\n");
 }
 else if (NULL == g_hSetTaskIdEvent)
 {
  printf("[Process] CreateEvent() Error, Errorcode: %d\n", iErrorCode);
 }
 else
 {
  printf("[Process] CreateEvent() Success!\n");
 }

 unsigned int nRunCnt = 0;
 while(nRunCnt < g_iMaxRunCnt)
 {
  bool bRunNext = false;   //初始置為false,不可以執行下面的操作。
  //等待信号觸發
  DWORD dwRst = WaitForSingleObject(g_hSetTaskIdEvent, INFINITE);
  switch(dwRst)
  {
  case WAIT_OBJECT_0:
   // The process terminated.
   printf("[Process]The state of the specified object is signaled.\n");
   bRunNext = true;
   break;
  case WAIT_TIMEOUT:
   // The process did not terminate within the given milliseconds.
   printf("[Process]The time-out interval elapsed, and the object's state is nonsignaled.\n");
   break;
  case WAIT_FAILED:
   // Bad call to function (invalid handle?)
   printf("[Process]WAIT_FAILED, ErrCode: %d\n", GetLastError());
   break;
  }//end switch
  //主線程運作後才可以執行下面的操作.
  if (bRunNext)
  {
   printf("[Process] The Process() Next can running!, running cnt = %d\n", nRunCnt++);
  }
  SetEvent(g_hSetTaskIdEvent);
 }
 CloseHandle(g_hSetTaskIdEvent);
 return 0;
}           

本質抽象為:事件同步機制。和sunxin教程的火車票模型基本完全一緻。

【反思】

1.當遇到複雜的邏輯,如:通信複雜、調用混亂,一定要先把思路梳理清楚;

2.當複雜的程式無法進行全局測試的時候,可以考慮抽象模型為小Demo,通過小Demo測試大緻架構邏輯的準确性。

作者:銘毅天下

轉載請标明出處,原文位址:

http://blog.csdn.net/laoyang360/article/details/45646151