std:: atomic_fetch_add, std:: atomic_fetch_add_explicit
|
定义于头文件
<atomic>
|
||
|
template
<
class
T
>
T atomic_fetch_add
(
std::
atomic
<
T
>
*
obj,
|
(1) | (C++11 起) |
|
template
<
class
T
>
T atomic_fetch_add
(
volatile
std::
atomic
<
T
>
*
obj,
|
(2) | (C++11 起) |
|
template
<
class
T
>
T atomic_fetch_add_explicit
(
std::
atomic
<
T
>
*
obj,
|
(3) | (C++11 起) |
|
template
<
class
T
>
T atomic_fetch_add_explicit
(
volatile
std::
atomic
<
T
>
*
obj,
|
(4) | (C++11 起) |
执行原子加法操作。原子地将 arg 加到 obj 所指向的值上,并返回 obj 先前持有的值。该操作的执行效果相当于以下代码:
如果
std::atomic<T>
没有
fetch_add
成员(该成员仅适用于
整型
、
浮点型
(C++20 起)
以及除
bool
外的
指针
类型),则程序非良构。
目录 |
参数
| obj | - | 指向要修改的原子对象的指针 |
| arg | - | 要添加到原子对象存储值中的数值 |
| order | - | 内存同步排序方式 |
返回值
在 * obj 的 修改顺序 中,紧邻此函数生效前的值。
示例
单写者/多读者锁可以通过
std::atomic_fetch_add
实现。注意这个简单实现不具备无锁性。
#include <atomic> #include <chrono> #include <iostream> #include <string> #include <thread> #include <vector> using namespace std::chrono_literals; // cnt的含义: // 5: 读者与写者竞争状态。无活跃读者或写者。 // 4...0: 存在1...5个活跃读者,写者被阻塞。 // -1: 写者赢得竞争,读者被阻塞。 const int N = 5; // 允许四个并发读者 std::atomic<int> cnt(N); std::vector<int> data; void reader(int id) { for (;;) { // 加锁 while (std::atomic_fetch_sub(&cnt, 1) <= 0) std::atomic_fetch_add(&cnt, 1); // 读取 if (!data.empty()) std::cout << ("reader " + std::to_string(id) + " sees " + std::to_string(*data.rbegin()) + '\n'); if (data.size() == 25) break; // 解锁 std::atomic_fetch_add(&cnt, 1); // 暂停 std::this_thread::sleep_for(1ms); } } void writer() { for (int n = 0; n < 25; ++n) { // 加锁 while (std::atomic_fetch_sub(&cnt, N + 1) != N) std::atomic_fetch_add(&cnt, N + 1); // 写入 data.push_back(n); std::cout << "writer pushed back " << n << '\n'; // 解锁 std::atomic_fetch_add(&cnt, N + 1); // 暂停 std::this_thread::sleep_for(1ms); } } int main() { std::vector<std::thread> v; for (int n = 0; n < N; ++n) v.emplace_back(reader, n); v.emplace_back(writer); for (auto& t : v) t.join(); }
输出:
writer pushed back 0 reader 2 sees 0 reader 3 sees 0 reader 1 sees 0 <...> reader 2 sees 24 reader 4 sees 24 reader 1 sees 24
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| DR | 适用范围 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| P0558R1 | C++11 |
由于
T
需要从多个参数进行推导,因此要求精确类型匹配
|
T
仅从
obj 进行推导 |
参阅
|
以原子方式将参数加到原子对象中存储的值上,并获取先前持有的值
(
std::atomic<T>
的公开成员函数)
|
|
|
(C++11)
(C++11)
|
从原子对象中减去非原子值并获取该原子的先前值
(函数模板) |
|
C 文档
用于
atomic_fetch_add
,
atomic_fetch_add_explicit
|
|