在多線程環境下,共享數據(如 std::vector、普通數組)的並發訪問需要加鎖保護。傳統做法需為每個共享對象顯式創建 pthread_mutex_t 或 CRITICAL_SECTION,導致:
Java/Objective-C 的 synchronized(object) 機制允許直接對任意對象加鎖,極大簡化了同步編程。
核心理念:用一個全局 Map 維護「對象地址 → 互斥鎖」的映射。雖引入查找開銷,但換取使用極致便利:
// aa_lock.h
class AALock {
public:
explicit AALock(void* object); // 構造時自動加鎖
~AALock(); // 析構時自動解鎖(RAII)
static void GLock(void* object); // 靜態手動加鎖
static void GUnLock(void* object); // 靜態手動解鎖
private:
void* lock_object_;
};
// aa_lock.cpp #include "aa_lock.h" #include#include
// test.cpp #include#include #include #include "aa_lock.h" const int MAX_COUNT = 10000; const int THREAD_NUM = 100; int64_t gCount = 0; std::vector gVec; void* ThreadFunc(void*) { for (int i = 0; i < MAX_COUNT; ++i) { // 對基本類型加鎖 AALock::GLock(&gCount); ++gCount; AALock::GUnLock(&gCount); // 對 vector 加鎖(非線程安全容器) AALock::GLock(&gVec); gVec.push_back(i); AALock::GUnLock(&gVec); } return nullptr; } int main() { pthread_t tids[THREAD_NUM]; for (int round = 0; round < 10; ++round) { gCount = 0; gVec.clear(); for (int i = 0; i < THREAD_NUM; ++i) pthread_create(&tids[i], NULL, ThreadFunc, NULL); for (int i = 0; i < THREAD_NUM; ++i) pthread_join(tids[i], NULL); assert(gCount == MAX_COUNT * THREAD_NUM); assert(gVec.size() == MAX_COUNT * THREAD_NUM); } return 0; }
gCount: 1000000 gVec size: 1000000 ... (重複 10 次,無崩潰、無數據競爭)
| 優點 | 缺點/注意事項 |
|---|---|
使用極簡:AALock lock(obj) 即自動管理 | Map 查找 + 雙重鎖(Map鎖+對象鎖)有微小性能損耗 |
| 無需預聲明鎖變量,天然支持跨模塊共享 | 鎖永不釋放,長期運行大量臨時對象可能泄漏 |
| RAII 保證異常安全 | 僅適用於進程內線程同步,不支持進程間 |
改進建議:引入引用計數,當對象無鎖持有者且無等待者時延遲銷毀鎖並從 Map 移除;Windows 下可替換為 CRITICAL_SECTION 或 SRWLOCK 提升性能。
AALock 以「約定優於配置」思想,用約 50 行核心代碼實現了類 synchronized 的對象級鎖語義,極大降低了 C++ 多線程同步的認知負擔與代碼雜訊,適合中小型項目快速開發。生產級項目建議根據性能剖析結果決定是否替換為細粒度顯式鎖。