使用互斥对象:
#include <windows.h> #include <iostream> #define THREADCOUNT 6 HANDLE ghMutex; DWORD WINAPI RunThreadFunction(LPVOID lpParam); int main(void) { HANDLE aThread[THREADCOUNT]; DWORD ThreadID; // 创建一个无所有者的互斥锁 ghMutex = CreateMutex( NULL, FALSE, NULL); if (ghMutex == NULL) { std::cout << "CreateMutex error: " << GetLastError() << std::endl; return 1; } for(int i = 0; i < THREADCOUNT; i++) { aThread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) RunThreadFunction, NULL, 0, &ThreadID); if( aThread[i] == nullptr ) { std::cout << "CreateThread error: " << GetLastError() << std::endl; return 1; } } // 等到所有线程都终止 WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); for(int i = 0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); // 关闭所有线程句柄并释放内存 CloseHandle(ghMutex); return 0; } DWORD WINAPI RunThreadFunction(LPVOID lpParam) { UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; for(int i = 0; i < 5; i++) { // 获得互斥权 dwWaitResult = WaitForSingleObject( ghMutex, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0: try { std::cout << i << " Thread " << GetCurrentThreadId() << " is run..."<< std::endl; } catch (...) { if (! ReleaseMutex(ghMutex)) // 释放互斥权 { std::cout << "ReleaseMutex error" << std::endl; } } break; // 线程处于不确定状态 case WAIT_ABANDONED: return FALSE; } } return TRUE; }
如果去掉互斥锁可看到输出十分混乱...原因也在于std::cout的输出是拼接的。如果用printf来输出会好一些,但输出的 i 可能是混乱的。
如下图:
加锁的运行结果:
下面是在MSDN看到的一个创建线程的例子,如果想要传递其他类型的参数且没有类型转换的警告,可以这样做:
#include <windows.h> #include <tchar.h> #include <strsafe.h> #define MAX_THREADS 3 #define BUF_SIZE 255 DWORD WINAPI MyThreadFunction( LPVOID lpParam ); void ErrorHandler(LPTSTR lpszFunction); typedef struct MyData { int val1; int val2; } MYDATA, *PMYDATA; int _tmain() { PMYDATA pDataArray[MAX_THREADS]; DWORD dwThreadIdArray[MAX_THREADS]; HANDLE hThreadArray[MAX_THREADS]; for( int i=0; i<MAX_THREADS; i++ ) { pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); if( pDataArray[i] == NULL ) { ExitProcess(2); } pDataArray[i]->val1 = i; pDataArray[i]->val2 = i+100; hThreadArray[i] = CreateThread( NULL, 0, MyThreadFunction, pDataArray[i], 0, &dwThreadIdArray[i]); if (hThreadArray[i] == NULL) { ErrorHandler((LPTSTR)TEXT("CreateThread")); ExitProcess(3); } } WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE); for(int i=0; i<MAX_THREADS; i++) { CloseHandle(hThreadArray[i]); if(pDataArray[i] != NULL) { HeapFree(GetProcessHeap(), 0, pDataArray[i]); pDataArray[i] = NULL; } } return 0; } DWORD WINAPI MyThreadFunction( LPVOID lpParam ) { HANDLE hStdout; PMYDATA pDataArray; TCHAR msgBuf[BUF_SIZE]; size_t cchStringSize; DWORD dwChars; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if( hStdout == INVALID_HANDLE_VALUE ) return 1; pDataArray = (PMYDATA)lpParam; StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), pDataArray->val1, pDataArray->val2); StringCchLength(msgBuf, BUF_SIZE, &cchStringSize); WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL); return 0; } void ErrorHandler(LPTSTR lpszFunction) { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); }
重点部分就是用到了结构型。