原子操作
std::atomic 禁用了拷贝构造函数和拷贝赋值运算符(因为拷贝操作无法原子化),所以不能直接 std::atomic<int> d = a;。
| 函数 | 内容 |
|---|---|
| atomic (T val) | 构造 |
| operator= | 构造,等号后面是 T 类型, 不能是atomic |
| {} | 大括号直接初始化 |
| is_lock_free() | 用于判断 std::atomic 的操作是 “真无锁(CPU 原子指令)” 还是 “假无锁(内置锁模拟) |
| store | 修改值 |
| load | 获取值 |
| operator T() | 获取值 |
| exchange | 用 val 替换所含值,并返回该值在操作前的原始值。 |
| compare_exchange_weak | 读取值并在比较成功时执行替换操作(替换成其他值) |
| compare_exchange_strong | 读取值并在比较成功时执行替换操作(替换成其他值) |
| fetch_add | 原值加上val, 返回操作前值 |
| fetch_sub | 原值减val, 返回操作前值 |
| fetch_and | 原值与val, 返回操作前值 |
| fetch_or | 原值或val, 返回操作前值 |
| fetch_xor | 原值异或val, 返回操作前值 |
| operator++ | |
| operator-- | |
| operator+= | 等同于fetch_add |
| operator-= | 等同于fetch_sub |
| operator&= | 等同于fetch_and |
| operator|= | 等同于fetch_or |
| operator^= | 等同于fetch_xor |
CAS 操作(Compare-And-Swap)
compare_exchange_weak/compare_exchange_strong 是 std::atomic 的核心,几乎所有无锁算法都基于 CAS 实现。
整个过程是不可中断的,完全由 CPU 硬件保证原子性,无需任何锁。
一句话概括:
我认为变量现在的值是 A,如果是,就把它改成 B;如果不是(说明被其他线程改了),就告诉我现在的值是多少,我不修改。
原理:
- 比较原子变量的当前值与 “预期值(expected)”;
- 如果相等:将原子变量更新为 “新值(desired)”,返回
true; - 如果不相等:将 “预期值” 更新为原子变量的当前值,返回
false; - 整个过程是原子的。
bool compare_exchange_strong(
T& expected, // 输入:预期值;输出:实际值(失败时)
T desired, // 目标值(成功时要设置的值)
std::memory_order success, // 成功时的内存序
std::memory_order failure // 失败时的内存序
) noexcept;
bool compare_exchange_weak (T& expected, T val, memory_order success, memory_order failure)
compare_exchange_strong和compare_exchange_weak区别在于伪失败
伪失败: 即使 当前值 == expected,weak 版本也可能返回 false(CPU 指令层面的偶然失败),但这种情况极少。
compare_exchange_strong性能低,但不会伪失败。
循环中用 weak 更高效 —— 即使偶尔伪失败,重试成本也远低于 strong 版本的严格检查。
#include <atomic>
#include <iostream>
int main() {
std::atomic<int> num{10};
int expected = 10;
int desired = 20;
// 循环重试,直到 CAS 成功
while (!num.compare_exchange_weak(expected, desired)) {
// 失败后,expected 已被更新为 num 的实际值,无需手动重置
std::cout << "CAS 失败,当前 expected:" << expected << std::endl;
}
std::cout << "CAS 成功,num 当前值:" << num << std::endl;
return 0;
}
自定义类型
自定义类型不建议使用std::atomic
建议使用`std::mutex` 加锁
C++20+:优先用 `std::atomic_ref` 简化自定义类型的原子操作。