std::atomic<T>::exchange

< cpp‎ | atomic‎ | atomic
T exchange( T desired, std::memory_order order =
                           std::memory_order_seq_cst ) noexcept;
(1) (C++11 起)
T exchange( T desired, std::memory_order order =
                           std::memory_order_seq_cst ) volatile noexcept;
(2) (C++11 起)

desired 原子地替换底层值。操作为读-修改-写操作。根据 order 的值影响内存。

重载 (2) 在参与重载决议且 std::atomic<T>::is_always_lock_freefalse 时被弃用。

(C++20 起)

参数

desired - 要赋值的值
order - 强制的内存定序约束

返回值

原子变量在调用前的值。

示例

#include <algorithm>
#include <atomic>
#include <cstddef>
#include <iostream>
#include <syncstream>
#include <thread>
#include <vector>
 
int main()
{
    constexpr int thread_count{5};
    constexpr int sum{5};
 
    std::atomic<int> atom{0};
    std::atomic<int> counter{0};
 
    auto increment_to_sum = [&](const int id)
    {
        for (int next = 0; next < sum;)
        {
            // 每个线程各自写入自身所知的值
            const int current = atom.exchange(next);
            counter++;
            // 同步写入,避免被其他线程中断
            std::osyncstream(std::cout)
                << "线程 #" << id << "(id=" << std::this_thread::get_id()
                << ")写入 " << next << ",替换旧值 "
                << current << "。\n";
            next = std::max(current, next) + 1;
        }
    };
 
    std::vector<std::thread> v;
    for (std::size_t i = 0; i < thread_count; ++i)
        v.emplace_back(increment_to_sum, i);
 
    for (auto& tr : v)
        tr.join();
 
    std::cout << thread_count << " 个线程总共用了 "
              << counter << " 次将 0 增加到 " << sum << "。\n";
}

可能的输出:

线程 #1(id=139722332333824)写入 0,替换旧值 0。
线程 #2(id=139722323941120)写入 0,替换旧值 0。
线程 #1(id=139722332333824)写入 1,替换旧值 0。
线程 #1(id=139722332333824)写入 2,替换旧值 1。
线程 #1(id=139722332333824)写入 3,替换旧值 2。
线程 #1(id=139722332333824)写入 4,替换旧值 3。
线程 #0(id=139722340726528)写入 0,替换旧值 0。
线程 #3(id=139722315548416)写入 0,替换旧值 0。
线程 #3(id=139722315548416)写入 1,替换旧值 4。
线程 #0(id=139722340726528)写入 1,替换旧值 1。
线程 #4(id=139722307155712)写入 0,替换旧值 1。
线程 #4(id=139722307155712)写入 2,替换旧值 2。
线程 #4(id=139722307155712)写入 3,替换旧值 2。
线程 #4(id=139722307155712)写入 4,替换旧值 3。
线程 #2(id=139722323941120)写入 1,替换旧值 0。
线程 #0(id=139722340726528)写入 2,替换旧值 1。
线程 #2(id=139722323941120)写入 2,替换旧值 4。
线程 #0(id=139722340726528)写入 3,替换旧值 2。
线程 #0(id=139722340726528)写入 4,替换旧值 3。
5 个线程总共用了 19 次将 0 增加到 5。

参阅

原子地以非原子实参的值替换原子对象的值,并返回该原子对象的旧值
(函数模板)
(C++14)
将实参替换为一个新值,并返回它先前的值
(函数模板)