用C++實現多執行緒Mutex鎖(Win32)
阿新 • • 發佈:2019-01-05
本文目的:用C++和Windows的互斥物件(Mutex)來實現執行緒同步鎖。
準備知識: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 : 定義控制檯應用程式的入口點。 // #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; }
用VC2005編譯,啟動程式,下邊是截圖
如果將測執行緒函式中的程式碼注視掉,重新編譯程式碼,執行
CLock lock(g_Lock);
則結果見下圖
由此可見,通過使用Mutex的封裝類,即可達到多執行緒同步的目的。因Mutex屬於核心物件,所以在進行多執行緒同步時速度會比較慢,但是用互斥物件可以在不同程序的多個執行緒之間進行同步。
在實際應用中,我們通常還會用到臨界區,也有叫做關鍵程式碼段的CRITICAL_SECTION,在下篇部落格中,我將會把CRITICAL_SECTION鎖新增進來,並且對Mutex和CRITICAL_SECTION的效能做以比較。