# std::atomic_compare_exchange_weak, std::atomic_compare_exchange_strong, std::atomic_compare_exchange_weak_explicit, std::atomic_compare_exchange_strong_explicit

< cpp‎ | atomic

定义于头文件 `<atomic>` |  |
| (1) | (C++11 起)
template< class T > bool atomic_compare_exchange_weak( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired ) noexcept; |  |
template< class T > bool atomic_compare_exchange_weak( volatile std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired ) noexcept; |  |
| (2) | (C++11 起)
template< class T > bool atomic_compare_exchange_strong( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired ) noexcept; |  |
template< class T > bool atomic_compare_exchange_strong( volatile std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired ) noexcept; |  |
| (3) | (C++11 起)
template< class T > bool atomic_compare_exchange_weak_explicit( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired, std::memory_order succ, std::memory_order fail ) noexcept; |  |
template< class T > bool atomic_compare_exchange_weak_explicit( volatile std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired, std::memory_order succ, std::memory_order fail ) noexcept; |  |
| (4) | (C++11 起)
template< class T > bool atomic_compare_exchange_strong_explicit( std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired, std::memory_order succ, std::memory_order fail ) noexcept; |  |
template< class T > bool atomic_compare_exchange_strong_explicit( volatile std::atomic<T>* obj, typename std::atomic<T>::value_type* expected, typename std::atomic<T>::value_type desired, std::memory_order succ, std::memory_order fail ) noexcept; |  |

原子地比较 `obj` 所指向对象与 `expected` 所指向对象的对象表示 (C++20 前)值表示 (C++20 起)，而若它们逐位相等，则以 `desired` 替换前者（进行读修改写操作）。否则，将 `obj` 所指向对象的实际值加载到 `*expected` （进行加载操作）。复制如同以 std::memcpy 进行。

读-修改-写和加载操作的内存模型各为 `succ` 和 `fail` 。 (1-2) 版本默认使用 std::memory_order_seq_cst 。

这些函数用 std::atomic 的成员函数定义：

1) obj->compare_exchange_weak(*expected, desired)
2) obj->compare_exchange_strong(*expected, desired)
3) obj->compare_exchange_weak(*expected, desired, succ, fail)
4) obj->compare_exchange_strong(*expected, desired, succ, fail)

### 参数

obj | - | 指向要测试和修改的原子对象的指针
expected | - | 指向期待在原子对象中找到的值的指针
desired | - | 若满足期待，则要存储于原子对象的值
succ | - | 若比较成功则用于读-修改-写操作的内存同步顺序。容许所有值。
fail | - | 若比较失败则用于加载操作的内存同步顺序。不能是 std::memory_order_release 或 std::memory_order_acq_rel 且不能指定强于 `succ` 的顺序 (C++17 前)

### 返回值

比较结果：若 `*obj` 等于 `*expected` 则为 true ，否则 false 。

### 注意

函数的弱形式（ (1) 与 (3) ）允许虚假地失败，即表现为如同 *obj != *expected ，即使它们相等。当比较并交换在循环中时，弱版本在某些平台上会生成更好的性能。

在弱版本会要求循环而强版本不要求时，更偏好强版本，除非 `T` 的对象表示可能包含t填充位、 (C++20 前)陷阱位，或者为一个值提供多个对象表示（例如浮点 NaN ）。这些情况下，弱的比较并交换经常有用，因为它在某些稳定对象表示上快速收敛。

若有些位参与 union 某些成员，但非其他成员的值表示，则比较和交换可能始终失败，因为这种填充位在不参与活跃成员的值表示时拥有不确定值。

忽略决不参与对象值表示的填充位。 | (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);

            // 将 head 的当前值放入 new_node->next
            new_node->next = head.load(std::memory_order_relaxed);

            // 现在令 new_node 为新的 head ，
            // 但若 head 不再是存储于 new_node->next 者
            // （某些其他线程必须已在现在插入结点）
            // 则将新的 head 放入 new_node->next 并重试
            while(!std::atomic_compare_exchange_weak_explicit(
                                    &head,
                                    &new_node->next,
                                    new_node,
                                    std::memory_order_release,
                                    std::memory_order_relaxed))
                    ; // 循环体为空
    // 注意：上述循环非线程安全，至少在
    // 早于 4.8.3 的 GCC （ bug 60272 ），早于 2014-05-05 的 clang （ bug 18899）
    // 早于 2014-03-17 的 MSVC （ bug 819819 ）。变通方法见成员函数版本
        }
    };

    int main()
    {
        stack<int> s;
        s.push(1);
        s.push(2);
        s.push(3);
    }

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
P0558R1 | C++11 | 曾要求准确类型匹配，因为从多个参数推导 `T` | 仅从 `atomic` 参数推导 `T`

### 参阅

compare_exchange_weak compare_exchange_strong | 原子地比较原子对象与非原子参数的值，若相等则进行交换，若不相等则进行加载 (`std::atomic<T>` 的公开成员函数)
atomic_exchange atomic_exchange_explicit (C++11)(C++11) | 原子地以非原子实参的值替换原子对象的值，并返回该原子对象的旧值 (函数模板)

std::atomic_compare_exchange_weak(std::shared_ptr) std::atomic_compare_exchange_strong(std::shared_ptr) (C++20 中弃用) | 为 std::shared_ptr 特化原子操作 (函数模板)