准備知識:1,內核對象互斥體(Mutex)的工作機理,WaitForSingleObject函數的用法,這些可以從MSDN獲取詳情;2,當兩個或 更多線程需要同時訪問一個共享資源時,系統需要使用同步機制來確保一次只有一個線程使用該資源。Mutex 是同步基元,它只向一個線程授予對共享資源的獨占訪問權。如果一個線程獲取了互斥體,則要獲取該互斥體的第二個線程將被掛起,直到第一個線程釋放該互斥體。
下邊是我參考開源項目C++ Sockets的代碼,寫的線程鎖類
Lock.h
#ifndef _Lock_H #define _Lock_H #include <windows.h> //鎖接口類 class IMyLock { public: virtual ~IMyLock() {} virtual void Lock() const = 0; virtual void Unlock() const = 0; }; //互斥對象鎖類 class Mutex : public IMyLock { public: Mutex(); ~Mutex(); virtual void Lock() const; virtual void Unlock() const; private: HANDLE m_mutex; }; //鎖 class CLock { public: CLock(const IMyLock&); ~CLock(); private: const IMyLock& m_lock; }; #endif
Lock.cpp
#include "Lock.h" //創建一個匿名互斥對象 Mutex::Mutex() { m_mutex = ::CreateMutex(NULL, FALSE, NULL); } //銷毀互斥對象,釋放資源 Mutex::~Mutex() { ::CloseHandle(m_mutex); } //確保擁有互斥對象的線程對被保護資源的獨自訪問 void Mutex::Lock() const { DWORD d = WaitForSingleObject(m_mutex, INFINITE); } //釋放當前線程擁有的互斥對象,以使其它線程可以擁有互斥對象,對被保護資源進行訪問 void Mutex::Unlock() const { ::ReleaseMutex(m_mutex); } //利用C++特性,進行自動加鎖 CLock::CLock(const IMyLock& m) : m_lock(m) { m_lock.Lock(); } //利用C++特性,進行自動解鎖 CLock::~CLock() { m_lock.Unlock(); }
下邊是測試代碼MyLock.cpp
// MyLock.cpp : 定義控制台應用程序的入口點。 // #include <iostream> #include <process.h> #include "Lock.h" using namespace std; //創建一個互斥對象 Mutex g_Lock; //線程函數 unsigned int __stdcall StartThread(void *pParam) { char *pMsg = (char *)pParam; if (!pMsg) { return (unsigned int)1; } //對被保護資源(以下打印語句)自動加鎖 //線程函數結束前,自動解鎖 CLock lock(g_Lock); for( int i = 0; i < 5; i++ ) { cout << pMsg << endl; Sleep( 500 ); } return (unsigned int)0; } int main(int argc, char* argv[]) { HANDLE hThread1, hThread2; unsigned int uiThreadId1, uiThreadId2; char *pMsg1 = "First print thread."; char *pMsg2 = "Second print thread."; //創建兩個工作線程,分別打印不同的消息 //hThread1 = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartThread, (void *)pMsg1, 0, (LPDWORD)&uiThreadId1); //hThread2 = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StartThread, (void *)pMsg2, 0, (LPDWORD)&uiThreadId2); hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg1, 0, &uiThreadId1); hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg2, 0, &uiThreadId2); //等待線程結束 DWORD dwRet = WaitForSingleObject(hThread1,INFINITE); if ( dwRet == WAIT_TIMEOUT ) { TerminateThread(hThread1,0); } dwRet = WaitForSingleObject(hThread2,INFINITE); if ( dwRet == WAIT_TIMEOUT ) { TerminateThread(hThread2,0); } //關閉線程句柄,釋放資源 ::CloseHandle(hThread1); ::CloseHandle(hThread2); system("pause"); return 0; }