# std::atomic<T>::compare_exchange_weak, std::atomic<T>::compare_exchange_strong

< cpp‎ | atomic‎ | atomic

定义于头文件 `<atomic>` |  |
| (1) | (C++11 起)
bool compare_exchange_weak( T& expected, T desired, std::memory_order success, std::memory_order failure ) noexcept; |  |
bool compare_exchange_weak( T& expected, T desired, std::memory_order success, std::memory_order failure ) volatile noexcept; |  |
| (2) | (C++11 起)
bool compare_exchange_weak( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |  |
bool compare_exchange_weak( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) volatile noexcept; |  |
| (3) | (C++11 起)
bool compare_exchange_strong( T& expected, T desired, std::memory_order success, std::memory_order failure ) noexcept; |  |
bool compare_exchange_strong( T& expected, T desired, std::memory_order success, std::memory_order failure ) volatile noexcept; |  |
| (4) | (C++11 起)
bool compare_exchange_strong( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |  |
bool compare_exchange_strong( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ) volatile noexcept; |  |

原子地比较 `*this` 和 `expected` 的对象表示 (C++20 前)值表示 (C++20 起)，而若它们逐位相等，则以 `desired` 替换前者（进行读修改写操作）。否则，将 `*this` 中的实际值加载进 `expected` （进行加载操作）。

读修改写和加载操作的内存模型分别为 `success` 和 `failure` 。在 (2) 和 (4) 版本中， `order` 用于读修改写操作和加载操作，除了若 order == std::memory_order_acq_rel 或 order == std::memory_order_release ，则加载操作分别使用 std::memory_order_acquire 和 std::memory_order_relaxed 。

若 std::atomic<T>::is_always_lock_free 为 false 则 volatile 限定版本被弃用。 | (C++20 起)

### 参数

expected | - | 到期待在原子对象中找到的值的引用。若比较失败则被存储 `*this` 的实际值。
desired | - | 若符合期待则存储于原子对象的值
success | - | 若比较成功，则读修改写操作所用的内存同步顺序。容许所有值。
failure | - | 若比较失败，则加载操作所用的内存同步顺序。不能为 std::memory_order_release 或 std::memory_order_acq_rel ，且不能指定强于 `success` 的顺序 (C++17 前)
order | - | 两个操作所用的内存同步顺序

### 返回值

若成功更改底层原子值则为 true ，否则为 false 。

### 注解

比较和复制是逐位的（类似 std::memcmp 和 std::memcpy ）；不使用构造函数、赋值运算符或比较运算符。

允许函数的弱形式 (1-2) 虚假地失败，即表现如同 *this != expected ，纵使它们相等。比较和交换在循环中时，弱版本在有的平台上会产出更好的性能。

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

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

忽略决不参与对象值表示的填充位。 | (C++20 起)

### 示例

比较和交换操作通常用作无锁数据结构的基本建筑块

    #include <atomic>
    template<typename T>
    struct node
    {
        T data;
        node* next;
        node(const T& data) : data(data), next(nullptr) {}
    };

    template<typename 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(!head.compare_exchange_weak(new_node->next, new_node,
                                            std::memory_order_release,
                                            std::memory_order_relaxed))
              ; // 循环体为空

    // 注意：上述使用至少在这些版本不是线程安全的
    // 先于 4.8.3 的 GCC （漏洞 60272 ），先于 2014-05-05 的 clang （漏洞 18899 ）
    // 先于 2014-03-17 的 MSVC （漏洞 819819 ）。下面是变通方法：
    //      node<T>* old_head = head.load(std::memory_order_relaxed);
    //      do {
    //          new_node->next = old_head;
    //       } while(!head.compare_exchange_weak(old_head, new_node,
    //                                           std::memory_order_release,
    //                                           std::memory_order_relaxed));
        }
    };
    int main()
    {
        stack<int> s;
        s.push(1);
        s.push(2);
        s.push(3);
    }

演示 compare_exchange_strong 如何要么更改原子对象的值，要么将变量用于比较。

| 本节未完成 原因：强 CAS 的更实际用法会更好，例如在 Concurrency in Action 使用它的地方

    #include <atomic>
    #include <iostream>

    std::atomic<int>  ai;

    int  tst_val= 4;
    int  new_val= 5;
    bool exchanged= false;

    void valsout()
    {
        std::cout << "ai= " << ai
                  << "  tst_val= " << tst_val
                  << "  new_val= " << new_val
                  << "  exchanged= " << std::boolalpha << exchanged
                  << "\n";
    }

    int main()
    {
        ai= 3;
        valsout();

        // tst_val != ai   ==>  tst_val 被修改
        exchanged= ai.compare_exchange_strong( tst_val, new_val );
        valsout();

        // tst_val == ai   ==>  ai 被修改
        exchanged= ai.compare_exchange_strong( tst_val, new_val );
        valsout();
    }

输出：

    ai= 3  tst_val= 4  new_val= 5  exchanged= false
    ai= 3  tst_val= 3  new_val= 5  exchanged= false
    ai= 5  tst_val= 3  new_val= 5  exchanged= true

### 参阅

atomic_compare_exchange_weak atomic_compare_exchange_weak_explicit atomic_compare_exchange_strong atomic_compare_exchange_strong_explicit (C++11)(C++11)(C++11)(C++11) | 原子地比较原子对象和非原子实参的值，若相等则进行 atomic_exchange，若不相等则进行 atomic_load (函数模板)