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) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_weak |
(2) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_strong |
(3) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_strong |
(4) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_weak_explicit |
(5) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_weak_explicit |
(6) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_strong_explicit |
(7) | (since C++11) (始于 C++11) |
template< class T > bool atomic_compare_exchange_strong_explicit |
(8) | (since C++11) (始于 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) | success (成功) | failure (失败) |
这些函数根据 成员函数 std::atomic 定义
如果 failure 强于 success 或(C++17 前) 是 std::memory_order_release 和 std::memory_order_acq_rel 之一,则行为未定义。
内容 |
[编辑] 参数
obj | - | 指向要测试和修改的原子对象的指针 |
expected (期望值) | - | 指向期望在原子对象中找到的值的指针 |
desired (期望值) | - | 如果要与期望值相同则存储在原子对象中的值 |
success (成功) | - | 如果比较成功,则读取-修改-写入操作的内存同步顺序 |
failure (失败) | - | 如果比较失败,则加载操作的内存同步顺序 |
[编辑] 返回值
比较的结果:如果 *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) |
原子地将原子对象的值替换为非原子参数,并返回原子的旧值 (函数模板) |
为 std::shared_ptr 特化原子操作 (函数模板) | |
C 文档 关于 atomic_compare_exchange, atomic_compare_exchange_explicit
|