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 起) |
原子地比较 obj 所指向对象的对象表示(C++20 前)值表示(C++20 起)与 expected 所指向对象的对象表示(C++20 前)值表示(C++20 起),如果它们是位等价的,则用 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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
P0558R1 | C++11 | 因为要求精确类型匹配T 是从多个参数推导出来的 |
T 仅从obj 中推导 |
[编辑] 参阅
原子地将原子对象的值与非原子参数进行比较,如果相等则执行原子交换,否则执行原子加载 ( std::atomic<T> 的公开成员函数) | |
(C++11)(C++11) |
原子地将原子对象的值替换为非原子参数,并返回原子的旧值 (函数模板) |
为 std::shared_ptr 特化原子操作 (函数模板) | |
C 文档 用于 atomic_compare_exchange, atomic_compare_exchange_explicit
|