習慣 C# lock() {} 或 Java synchronized() {} 的開發者,初用 Windows 臨界區、互斥體、事件、信號量常感不順手。本文示範如何用 RAII 模式封裝臨界區,實現語法簡潔、異常安全、自動釋放的 synchronized(mutex) { ... } 風格同步鎖。
// Mutex.h
class Mutex {
public:
Mutex();
~Mutex();
void Lock();
void Unlock();
private:
CRITICAL_SECTION m_criticalSection;
};
// Mutex.cpp
#include "Mutex.h"
Mutex::Mutex() { InitializeCriticalSection(&m_criticalSection); }
Mutex::~Mutex() { DeleteCriticalSection(&m_criticalSection); }
void Mutex::Lock() { EnterCriticalSection(&m_criticalSection); }
void Mutex::Unlock() { LeaveCriticalSection(&m_criticalSection); }
// Lock 定義於 Mutex.h
class Lock {
public:
explicit Lock(Mutex& mutex);
~Lock();
void SetUnlock(); // 提前解鎖標記
operator bool() const; // 用於 for 迴圈條件判斷
private:
Mutex& m_mutex;
bool m_locked;
};
// Lock.cpp
#include "Mutex.h"
Lock::Lock(Mutex& mutex) : m_mutex(mutex), m_locked(true) {
m_mutex.Lock();
}
Lock::~Lock() {
if (m_locked) m_mutex.Unlock(); // 離開作用域自動解鎖
}
void Lock::SetUnlock() { m_locked = false; }
Lock::operator bool() const { return m_locked; }
#define synchronized(M) \
for (Lock M##_lock = M; M##_lock; M##_lock.SetUnlock())
原理:for 迴圈初始化建立 Lock 物件 (上鎖),條件判斷 operator bool() 為真執行迴圈體,迴圈結束呼叫 SetUnlock() 將標記設為 false,下次條件判斷失效跳出,解構函數執行解鎖。無論迴圈體是否拋出異常,Lock 解構函數都會執行,保證釋放鎖。
Mutex _mutex;
{
Lock lock(_mutex); // 手動 RAII
// ... 同步區段 ...
}
Mutex mutex1;
int thread_count = 0;
DWORD CALLBACK thread_proc(LPVOID) {
for (int i = 0; i < 10; ++i) {
synchronized(mutex1) { // 整齊劃一的同步區塊
for (char c = 'A'; c <= 'Z'; ++c) {
printf("%c", c);
Sleep(2);
}
printf("\n");
}
}
thread_count--;
return 0;
}
int main() {
thread_count = 4;
CreateThread(0, 0, thread_proc, 0, 0, 0);
CreateThread(0, 0, thread_proc, 0, 0, 0);
CreateThread(0, 0, thread_proc, 0, 0, 0);
CreateThread(0, 0, thread_proc, 0, 0, 0);
while (thread_count) Sleep(0);
getchar();
return 0;
}
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
... (四條執行緒依序輸出,無交錯)
完美同步!每個執行緒完整輸出 A-Z 後釋放鎖,下一執行緒才進入。
synchronized(mutex) { ... } 一目瞭然std::mutex (C++11) 或跨平台實作Mutex (核心物件)std::lock_guard<std::mutex>