程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 用C++實現多線程Mutex鎖

用C++實現多線程Mutex鎖

編輯:C++入門知識

 

  本文目的:用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,在下篇博客中,我將會把關鍵代碼段鎖添加進來,並且對Mutex和CRITICAL_SECTION的性能做以比較

摘自 chexlong的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved