標籤:
原chexlong 原文地址:http://blog.csdn.net/chexlong/article/details/7051193
本文目的:用C++和Windows的互斥對象(Mutex)來實現線程同步鎖。
準備知識:1,核心對象互斥體(Mutex)的工作機理,WaitForSingleObject函數的用法,這些可以從MSDN擷取詳情; 2,當兩個或更多線程需要同時訪問一個共用資源時,系統需要使用同步機制來確保一次只有一個線程使用該資源。Mutex 是同步基元,它只向一個線程授予對共用資源的獨佔訪問權。如果一個線程擷取了互斥體,則要擷取該互斥體的第二個線程將被掛起,直到第一個線程釋放該互斥體。
下邊是我參考開源項目C++ Sockets的代碼,寫的線程鎖類
Lock.h
[cpp] view plaincopy
- #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
[cpp] view plaincopy
- #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();
- }
下邊是測試代碼
[cpp] view plaincopy
- // 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編譯,啟動程式,下邊是
如果將測線程函數中的代碼注視掉,重新編譯代碼,運行
[cpp] view plaincopy
- CLock lock(g_Lock);
則結果見
由此可見,通過使用Mutex的封裝類,即可達到多線程同步的目的。因Mutex屬於核心對象,所以在進行多線程同步時速度會比較慢,但是用互斥對象可以在不同進程的多個線程之間進行同步。
在實際應用中,我們通常還會用到臨界區,也有叫做關鍵程式碼片段的CRITICAL_SECTION,在下篇部落格中,我將會把CRITICAL_SECTION鎖添加進來,並且對Mutex和CRITICAL_SECTION的效能做以比較。
【轉】用C++實現多線程Mutex鎖(Win32)