std::atomic<T>::exchange
来自cppreference.com
| |
(1) | (C++11 起) |
| |
(2) | (C++11 起) |
以 desired 原子地替换底层值。操作为读-修改-写操作。根据 order 的值影响内存。
|
重载 (2) 在参与重载决议且 |
(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++11)(C++11) |
原子地以非原子实参的值替换原子对象的值,并返回该原子对象的旧值 (函数模板) |
(C++14) |
替换实参为一个新值,并返回它先前的值 (函数模板) |