C++原子读/写误解

c++ atomic read/write misunderstanding

本文关键字:误解 C++      更新时间:2023-10-16

为什么使用此代码的程序有时会打印"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,而不考虑两者之间可能发生的原子操作。

因此,您可以有以下方案:

  1. t1t2原子递增a现在等于 1。
  2. t3原子加载 1。
  3. t1t2原子递增a现在等于 2。
  4. t3对先前加载的值执行非原子加法,并以原子方式存储回 2。