自旋鎖適合競爭輕微、臨界區極短的情況(驅動、內核常用)。本文提供純用戶態、跨平台(Win32+VC / Linux+GCC≥4.1.2)的 C 介面實現。
typedef struct {
volatile long flag_; // 鎖標誌位(或指向外部標誌)
volatile long* spin_; // 實際自旋變數位址
} spin_lock_t;
void spin_init(spin_lock_t* lock, long* flag); // flag=NULL 時用內部 flag_
void spin_lock(spin_lock_t* lock); // 阻塞式獲取
int spin_trylock(spin_lock_t* lock); // 非阻塞嘗試
void spin_unlock(spin_lock_t* lock); // 釋放
int spin_is_lock(spin_lock_t* lock); // 查詢狀態
| 語意 | Windows (VC) | Linux (GCC ≥4.1.2) |
|---|---|---|
| 原子交換 | InterlockedExchange | __sync_lock_test_and_set |
| 原子或後取舊值 | InterlockedOr (Vista+) | __sync_fetch_and_or |
| 原子加後取新值 | InterlockedExchangeAdd | __sync_add_and_fetch |
| 原子與後取新值 | InterlockedAnd (Vista+) | __sync_and_and_fetch |
| CPU 讓出 | Sleep(1) | sched_yield() |
void spin_lock(spin_lock_t* lock) {
#ifdef _MSC_VER
for (; 0 != InterlockedExchange((volatile long*)lock->spin_, 1); )
Sleep(1);
#elif defined(__GNUC__)
for (; 0 != __sync_fetch_and_or(lock->spin_, 1); )
sched_yield();
#endif
}
void spin_unlock(spin_lock_t* lock) {
#ifdef _MSC_VER
InterlockedExchange((volatile long*)lock->spin_, 0);
#elif defined(__GNUC__)
__sync_and_and_fetch(lock->spin_, 0);
#endif
}
spin_ 可指向外部標誌,支援多鎖共享單一旗標(如陣列鎖);volatile 防止編譯器優化掉自旋讀寫;自旋等待時呼叫 Sleep(1) / sched_yield() 釋放時間片,避免佔滿 CPU。若臨界區極短(幾十指令),可改為 _mm_pause() / __builtin_ia32_pause() 總線鎖優化。