我多次运行以下代码,但为什么前缀增量的结果,fetch_add()显示正确的结果,而使用添加操作(+),它会输出错误的结果?
#include <iostream>
#include <mutex>
#include <future>
using namespace std;
atomic <int> cnt (0);
void fun()
{
for(int i =0; i <10000000 ; ++i)
{
//++cnt; // print the correct result 20000000
//cnt = cnt+1; // print wrong result, arbitrary numbers
cnt.fetch_add(1); // print the correct result 20000000
}
}
int main()
{
auto fut1 = async(std::launch::async, fun);
auto fut2 = async(std::launch::async, fun);
fut1.get();
fut2.get();
cout << "value of cnt: "<<cnt <<endl;
}
Run Code Online (Sandbox Code Playgroud)
Rem*_*eau 29
++cnt并且cnt.fetch_add(1)是真正的原子操作.一个线程被阻塞,而另一个线程读取,递增并更新该值.因此,两个线程不能互相踩到脚趾.访问权限cnt是完全序列化的,最终结果如您所料.
cnt = cnt+1;不是完全原子的.它涉及三个独立的操作,其中只有两个是原子的,但一个不是.当一个线程以原子方式读取当前值cnt并在本地复制它时,另一个线程不再被阻塞,并且可以cnt在该副本递增时随意自由修改.然后,将递增的副本分配回cnt原子,但如果cnt已被另一个线程修改,则将分配过时的值.所以最终结果是随机的而不是你所期望的.
tas*_*oor 10
cnt = cnt+1
这不是原子操作.这首先cnt在一个原子操作中加载,然后进行添加并最终将结果存储在另一个原子操作中.但是,加载后可以更改该值,最终存储可能会覆盖该值,从而导致错误的最终结果.
另外两个是原子操作,因此避免了这种竞争条件.
请注意,运算符++, --, +=, -=, &=, |=, ^=被重载std::atomic以提供原子操作.
| 归档时间: |
|
| 查看次数: |
1625 次 |
| 最近记录: |