c ++原子读/写误解

时间:2014-11-27 22:37:52

标签: c++ multithreading atomic

为什么使用此代码的程序有时会打印“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,但我无法理解为什么它是错误的。

1 个答案:

答案 0 :(得分:27)

与其他两个线程不同,

t3不执行原子添加。相反,它以原子方式加载a,在临时上执行算术(加1),并将该新值原子地存储回a。无论两者之间可能发生的原子操作如何,都会覆盖a

所以你可以有以下场景:

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