C++原子读/写误解
c++ atomic read/write misunderstanding
为什么使用此代码的程序有时会打印"2"?
int main() {
std::atomic<int> a;
a = 0;
std::thread t1([&]{++a;});
std::thread t2([&]{a++;});
std::thread t3([&]{
a = a.load() + 1;
});
t1.join();
t2.join();
t3.join();
if (a != 3) {
std::cout << "a: " << a << std::endl;
}
}
我认为std::atomic
保证所有操作都将以原子方式完成,因此在此处编写(递增)将使用内存屏障,并且我们将始终在线程工作结束时3
。我已经浏览了代码并发现问题线程t3
但我不明白为什么它是错误的。
t3
与其他两个线程不同,它不执行原子加法。相反,它以原子方式加载a
,对临时值执行算术(加 1),并以原子方式将该新值存储回a
。这将覆盖a
,而不考虑两者之间可能发生的原子操作。
因此,您可以有以下方案:
-
t1
或t2
原子递增a
现在等于 1。 -
t3
原子加载 1。 -
t1
或t2
原子递增a
现在等于 2。 -
t3
对先前加载的值执行非原子加法,并以原子方式存储回 2。
相关文章:
- #if 如何工作?我误解了 #if~#endif 的形式吗?
- 毕达哥拉斯三重嵌套循环误解
- 误解可变参数模板函数
- C++:误解内存地址和指针的复制值
- C++14 线程/条件变量误解
- CPP继承有些误解
- 我是否误解了此默认参数共享的范围
- 对Liinux上静态链接的误解
- 类大括号初始化被误解为 std::initializer_list 而不是复制构造
- 动态加载库和运行时误解的显式链接
- 编译器函数中的误解
- 我应该将分配器作为函数参数传递吗?(我对分配器的误解)
- MSVC 19.11 / Visual C 2017:尺寸1和size_t类型的初始化列表误解
- SPIMI算法误解
- C++一般的继承误解
- 填充和对齐 - 误解
- C++中对数组的误解
- 误解了 std::runtime_error 的 what() 函数
- 我误解了这个伪代码了吗
- 对 std::numeric_limits<double>::d igits10 的误解