目錄
std::atomic ::compare_exchange_weak?和?std::atomic ::compare_exchange_strong?
核心原理
函數簽名
核心區別
典型用法
1.?compare_exchange_weak(循環內重試)
2.?compare_exchange_strong(單次嘗試)
底層機制
總結
std::atomic<T>::compare_exchange_weak
?和?std::atomic<T>::compare_exchange_strong
?
核心原理
這兩個函數都是?原子比較-交換(Compare-and-Swap, CAS)?操作,屬于無鎖編程的基礎操作。其偽代碼邏輯如下:
bool compare_exchange(T& expected, T desired) {if (atomic_value == expected) {atomic_value = desired; // 交換成功return true;} else {expected = atomic_value; // 更新 expected 為當前值return false;}
}
關鍵點:整個操作是原子的(不可中斷),用于實現無鎖數據結構(如隊列、棧)。
函數簽名
bool compare_exchange_weak(T& expected, T desired, memory_order success = memory_order_seq_cst,memory_order failure = memory_order_seq_cst);bool compare_exchange_strong(T& expected, T desired,memory_order success = memory_order_seq_cst,memory_order failure = memory_order_seq_cst);
-
expected
:傳入期望值,失敗時會被更新為原子變量的當前值。 -
desired
:交換成功時設置的目標值。 -
內存序:
success
(成功時的內存序)和?failure
(失敗時的內存序)。
核心區別
特性 | compare_exchange_weak | compare_exchange_strong |
---|---|---|
虛假失敗 | 可能(即使值相等也返回?false ) | 不可能(僅在值不相等時失敗) |
性能 | 更高(某些平臺減少重試開銷) | 稍低(保證嚴格比較) |
適用場景 | 循環內重試(如自旋鎖) | 單次嘗試或無循環場景 |
硬件依賴 | 在 ARM/PowerPC 等平臺可能虛假失敗 | 所有平臺行為一致 |
典型用法
1.?compare_exchange_weak
(循環內重試)
std::atomic<int> val(10);
int expected = val.load(); // 獲取當前值do {int desired = expected * 2; // 計算新值// 弱版本允許虛假失敗,需配合循環
} while (!val.compare_exchange_weak(expected, desired));
-
適用場景:自旋鎖、無鎖隊列等需反復重試的操作。
2.?compare_exchange_strong
(單次嘗試)
std::atomic<bool> flag(false);
bool expected = false;// 僅嘗試一次,強版本保證無虛假失敗
if (flag.compare_exchange_strong(expected, true)) {// 成功獲取鎖
} else {// 已被其他線程修改
}
-
適用場景:單次檢查或無需重試的邏輯。
底層機制
-
弱版本:
某些硬件(如 ARM)的 CAS 操作可能因緩存一致性協議(如 MESI)或線程調度導致虛假失敗,但硬件實現更高效。 -
強版本:
在弱版本基礎上封裝循環,直到成功或真實失敗:
bool compare_exchange_strong(...) {while (!compare_exchange_weak(...)) {if (atomic_value != expected) break; // 真實失敗退出}
}
總結
場景 | 推薦函數 |
---|---|
循環內重試(如自旋鎖) | compare_exchange_weak |
單次嘗試或無循環邏輯 | compare_exchange_strong |
需最高性能(低競爭環境) | weak ?+ 循環 |
需代碼簡潔性 | strong (避免手動重試) |
最佳實踐:
在循環中優先使用?weak
(如實現無鎖棧/隊列),非循環場景用?strong
。例如:
// 無鎖棧的 push 操作
void push(Node* new_node) {Node* old_head = head.load();do {new_node->next = old_head;} while (!head.compare_exchange_weak(old_head, new_node));
}