首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++ 實現類 C# lock / Java synchronized 的 RAII 鎖封裝

     編輯:VC 教學

動機:告別繁瑣的手動 Lock/Unlock

Windows 原生同步物件(Critical Section、Mutex、Event、Semaphore)雖強大,但需手動配對呼叫 Enter/Leave 或 Wait/Signal,一旦函數中途 return、拋出異常或 goto 跳轉,極易造成死鎖或資源洩漏。C# lock(obj)、Java synchronized(obj) 以語法糖保證「進入區塊即加鎖、離開區塊必解鎖」。本文展示如何在 C++ 中用 RAII (Resource Acquisition Is Initialization) 模式實現同等體驗。

一、底層 Mutex 封裝(薄包裝 Critical Section)

// Mutex.h
#pragma once
#include 

class Mutex {
public:
    Mutex()  { InitializeCriticalSection(&m_cs); }
    ~Mutex() { DeleteCriticalSection(&m_cs); }

    void Lock()   { EnterCriticalSection(&m_cs); }
    void Unlock() { LeaveCriticalSection(&m_cs); }

    // 禁止拷貝/移動,避免雙重釋放
    Mutex(const Mutex&) = delete;
    Mutex& operator=(const Mutex&) = delete;

private:
    CRITICAL_SECTION m_cs;
};

Critical Section 輕量、用戶態、適合進程內執行緒同步;跨進程請改用 CreateMutex 封裝。

二、RAII Lock Guard 類別

// Mutex.h (續)
class Lock {
public:
    explicit Lock(Mutex& m) : m_mutex(m), m_locked(true) {
        m_mutex.Lock();
    }
    ~Lock() {
        if (m_locked) m_mutex.Unlock(); // 析構自動解鎖,異常安全
    }

    // 支援 synchronized 宏所需的介面
    void SetUnlock() { m_locked = false; } // 提前釋放鎖
    operator bool() const { return m_locked; } // for 迴圈條件判斷

private:
    Mutex& m_mutex;
    bool   m_locked;

    Lock(const Lock&) = delete;
    Lock& operator=(const Lock&) = delete;
};

三、語法糖宏:synchronized(mutex)

#define synchronized(M) \
    for (Lock M##_lock = M; M##_lock; M##_lock.SetUnlock())

原理:for(init; condition; increment) 只執行一次迴圈體。
init 建立 Lock 物件並加鎖;
condition 呼叫 operator bool() 返回 true 進入迴圈體;
迴圈體結束執行 increment → SetUnlock() 標記已解鎖;
下一次 condition 為 false 退出迴圈,Lock 析構(若未提前解鎖則再次解鎖,雙重保險)。

四、使用範例

Mutex g_dataMutex;
std::vector g_sharedData;

void ThreadSafePush(int val) {
    synchronized(g_dataMutex) {
        g_sharedData.push_back(val); // 區塊結束自動解鎖
        if (val < 0) throw std::runtime_error("negative"); // 異常也安全
    }
}

int ThreadSafePop() {
    synchronized(g_dataMutex) {
        if (g_sharedData.empty()) return -1;
        int v = g_sharedData.back();
        g_sharedData.pop_back();
        return v; // 正常返回自動解鎖
    }
}

五、進階擴充建議

  1. 遞迴鎖:Critical Section 原生支援遞迴,無需額外邏輯。
  2. 讀寫鎖:Windows 7+ 提供 SRWLOCK,可封裝 SharedLock/ExclusiveLock。
  3. 超時鎖:需用 Mutex 核心物件 + WaitForSingleObject,RAII 包裝時在建構函數處理超時邏輯。
  4. C++17 std::scoped_lock / std::lock_guard:現代專案優先使用標準庫,僅在維護舊代碼或需跨平台相容 Windows XP 時採用本實現。

六、總結

以 Mutex 封裝底層同步物件、Lock 實現 RAII、macro 提供語法糖 三層架構,僅 50 行核心代碼即可在 C++ 中獲得 C#/Java 級別的鎖使用體驗:簡潔、異常安全、零洩漏。這正是「現代 C++ 風格」在舊代碼庫中的實用落地。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved