windows C++ 互相等待線程同步示例
開發中遇到線程同步問題,可抽象為如下模型:
1、主線程的繼續執行的前提是子線程的變量已經初始化完畢。
2、子線程待主線程執行完畢後繼續執行後續的初始化操作。
重複1,2執行……直到通信結束。
如下圖所示:
源碼(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