用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

// 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; 
} 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM