【C/C++】无锁编程——compare_exchange_strong
文章目录
- 原子操作之compare_exchange_strong
- 1 简介
- 2 核心
- 2 语法
- 3 与 compare_exchange_weak的区别
- 4 使用场景示例
- 4.1 无锁计数器
- 4.2 线程安全栈(Treiber Stack)
- 5 内存序(Memory Order)参数
- 6 关键注意事项
- 7 总结
原子操作之compare_exchange_strong
1 简介
std::atomic
类型提供的一个关键原子操作.
作用:
- 实现无锁(lock-free)编程中的 比较并交换(Compare-and-Swap, CAS)。
- 确保在多线程环境中安全地修改共享数据,避免竞态条件(race condition)。
2 核心
-
比较并交换:
- 输入参数:
expected
:期望的旧值(引用传递,操作后可能被修改)。desired
:希望设置的新值。memory_order
:内存序(可选,默认std::memory_order_seq_cst
)。
- 操作逻辑:
- 如果原子变量的当前值等于
expected
,则将其设置为desired
,并返回true
。 - 如果当前值不等于
expected
,则将expected
更新为当前值,并返回false
。
- 如果原子变量的当前值等于
- 输入参数:
-
原子性保证:
- 整个操作是原子的,不会被其他线程中断。
2 语法
bool compare_exchange_strong(T& expected, T desired,std::memory_order order = std::memory_order_seq_cst
);
3 与 compare_exchange_weak的区别
特性 | compare_exchange_strong | compare_exchange_weak |
---|---|---|
伪失败 | 永远不会伪失败(总是严格的 CAS) | 允许在某些平台返回伪失败(即使值匹配) |
适用场景 | 需要确保操作成功的一次性场景 | 循环中重试的场景(如自旋锁) |
性能 | 可能略低(需严格检查) | 可能更高(允许硬件优化) |
典型代码模式 | 单次检查(如无锁队列的精确条件) | 循环重试(如 while (!weak(...)) ) |
4 使用场景示例
4.1 无锁计数器
std::atomic<int> counter{0};void increment() {int old_val = counter.load();while (true) {int new_val = old_val + 1;if (counter.compare_exchange_strong(old_val, new_val)) {break; // 成功递增}// 失败时 old_val 已更新为当前值,继续重试}
}
4.2 线程安全栈(Treiber Stack)
template<typename T>
class LockFreeStack {struct Node {T data;Node* next;};std::atomic<Node*> head{nullptr};public:void push(const T& value) {Node* new_node = new Node{value, head.load()};while (!head.compare_exchange_strong(new_node->next, new_node));}bool pop(T& value) {Node* old_head = head.load();while (old_head && !head.compare_exchange_strong(old_head, old_head->next)) {}if (!old_head) return false;value = old_head->data;delete old_head;return true;}
};
5 内存序(Memory Order)参数
compare_exchange_strong
接受以下内存序(控制操作的原子性和可见性):
std::memory_order_relaxed
:无同步(仅保证原子性)。std::memory_order_acquire
:当前线程的后续读操作必须在此操作后执行。std::memory_order_release
:当前线程的前序写操作必须在此操作前完成。std::memory_order_acq_rel
:结合acquire
和release
。std::memory_order_seq_cst
:全局顺序一致性(默认,性能最低)。
6 关键注意事项
-
ABA 问题:
- 如果
expected
值在操作期间被其他线程修改为其他值后又改回原值,compare_exchange_strong
会误认为值未变。 - 解决方案:使用带版本号的原子变量(如
std::atomic<std::pair<T, uint64_t>>
)或hazard pointer
。
- 如果
-
循环重试:
- 在冲突激烈时,
compare_exchange_strong
可能导致忙等待(busy-wait),需结合退避策略(如指数退避)。
- 在冲突激烈时,
-
性能优化:
- 在循环中使用
compare_exchange_weak
更高效(如自旋锁),而compare_exchange_strong
适合单次检查。
- 在循环中使用
7 总结
compare_exchange_strong
是 C++ 无锁编程的核心工具,通过严格的 CAS 语义保证线程安全。使用时需结合内存序参数、循环重试机制,并警惕 ABA 问题。在需要精确条件判断时优先使用 strong
版本,而在循环中可优先使用 weak
版本以提升性能。