用C++和Windows的互斥對象(Mutex)來實現線程同步鎖


用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編譯,啟動程序,下邊是截圖

\" src=

 

    如果將測線程函數中的代碼注視掉,重新編譯代碼,運行

 

CLock lock(g_Lock);

     則結果見下圖

\" src=

 

    由此可見,通過使用Mutex的封裝類,即可達到多線程同步的目的。因Mutex屬於內核對象,所以在進行多線程同步時速度會比較慢,但是用互斥對象可以在不同進程的多個線程之間進行同步。

    在實際應用中,我們通常還會用到關鍵代碼段CRITICAL_SECTION,在下篇博客中,我將會把關鍵代碼段鎖添加進來,並且對Mutex和CRITICAL_SECTION的性能做以比較


免責聲明!

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



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