std::atomic_compare_exchange_weak, std::atomic_compare_exchange_strong, std::atomic_compare_exchange_weak_explicit, std::atomic_compare_exchange_strong_explicit
定义于头文件 <atomic> |
||
template< class T > bool atomic_compare_exchange_weak |
(1) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_weak |
(2) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_strong |
(3) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_strong |
(4) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_weak_explicit |
(5) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_weak_explicit |
(6) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_strong_explicit |
(7) | (自 C++11 起) |
template< class T > bool atomic_compare_exchange_strong_explicit |
(8) | (自 C++11 起) |
原子地比较 对象表示(直至 C++20)值表示(自 C++20 起) 由 obj 指向的对象与由 expected 指向的对象,若它们按位相等,则将前者替换为 desired(执行读-改-写操作)。否则,将由 obj 指向的实际值加载到 *expected 中(执行加载操作)。
重载 | 内存模型,用于 | |
---|---|---|
读-改-写 操作 | 加载操作 | |
(1-4) | std::memory_order_seq_cst | std::memory_order_seq_cst |
(5-8) | 成功 | 失败 |
这些函数是根据 成员函数 std::atomic 定义的
若 failure 强于 success 或(直至 C++17) 是 std::memory_order_release 和 std::memory_order_acq_rel 之一,则行为未定义。
目录 |
[编辑] 参数
obj | - | 指向要测试和修改的原子对象的指针 |
expected | - | 指向预期在原子对象中找到的值的指针 |
desired | - | 若原子对象与预期值一致,则要存储在原子对象中的值 |
成功 | - | 若比较成功,则为读-改-写操作的内存同步顺序 |
失败 | - | 若比较失败,则为加载操作的内存同步顺序 |
[编辑] 返回值
比较的结果:若 *obj 等于 *expected,则为 true,否则为 false。
[编辑] 注意
std::atomic_compare_exchange_weak
和 std::atomic_compare_exchange_weak_explicit
(弱版本)允许虚假失败,即即使 *obj != *expected 相等,也表现得如同它们不相等。当比较并交换在循环中时,它们在某些平台上会产生更好的性能。
当弱比较并交换需要循环而强比较并交换不需要循环时,强比较并交换更佳,除非 T
的对象表示可能包含 填充位、(直至 C++20)陷阱位,或为相同的值提供多个对象表示(例如浮点 NaN)。在这些情况下,弱比较并交换通常有效,因为它会快速收敛到某个稳定的对象表示。
对于某些成员的值表示中包含某些位但不包含其他位的联合体,比较并交换可能总是失败,因为当这些填充位不参与活动成员的值表示时,它们具有不确定的值。
从不参与对象的值表示的填充位会被忽略。 |
(自 C++20 起) |
[编辑] 示例
比较并交换操作通常用作无锁数据结构的基本构建块。
#include <atomic> template<class T> struct node { T data; node* next; node(const T& data) : data(data), next(nullptr) {} }; template<class T> class stack { std::atomic<node<T>*> head; public: void push(const T& data) { node<T>* new_node = new node<T>(data); // put the current value of head into new_node->next new_node->next = head.load(std::memory_order_relaxed); // now make new_node the new head, but if the head // is no longer what's stored in new_node->next // (some other thread must have inserted a node just now) // then put that new head into new_node->next and try again while (!std::atomic_compare_exchange_weak_explicit( &head, &new_node->next, new_node, std::memory_order_release, std::memory_order_relaxed)) ; // the body of the loop is empty // note: the above loop is not thread-safe in at least // GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899) // MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround } }; int main() { stack<int> s; s.push(1); s.push(2); s.push(3); }
[编辑] 缺陷报告
下列更改行为的缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布时的行为 | 正确行为 |
---|---|---|---|
P0558R1 | C++11 | 需要精确的类型匹配,因为T 是从多个参数推导出的 |
T 仅从obj 推导 |
[编辑] 参见
原子地比较原子对象的值与非原子参数,若相等则执行原子交换,否则执行原子加载 ( std::atomic<T> 的公有成员函数) | |
(C++11)(C++11) |
原子地将原子对象的值替换为非原子参数,并返回原子对象的旧值 (函数模板) |
(已在 C++20 中弃用)(已在 C++26 中移除) |
针对 std::shared_ptr 特化原子操作 (函数模板) |
C 文档,用于 atomic_compare_exchange,atomic_compare_exchange_explicit
|