对原子变量进行非原子操作,以及对非原子变量进行原子操作。

3

给定以下代码:

static int x;

static void f() {
  for (int i = 0; i < 100; ++i)
    atomic_fetch_add(&x, 3);
}

此外,假设f被两个线程同时调用。C/C++内存模型是否保证在所有硬件平台上的结果始终是600

如果我将它更改为以下内容呢?在所有硬件平台上,结果是否仍然保证为600

static atomic_int a_x;

static void f() {
  for (int i = 0; i < 100; ++i)
    a_x += 3;
}

那么结果就不能保证,并且我不应该混合使用原子操作和非原子类型,反之亦然吗?

附注:这里我使用了int类型,但我的问题适用于任何类型T 和 _Atomic T。


2
你在 atomic_fetch_add() 参考文献 中具体不清楚什么? - πάντα ῥεῖ
2
如果你在C和C++之间做出选择,那么回答这个问题会更容易。 - klutt
简而言之:原子和非原子类型的指针不兼容,因此将“&x”传递给“atomic_fetch_add”是无效的。 - trent
第二段代码保证会使 a_x == 100。内置的自增、自减和复合赋值运算符是读取-修改-写入原子操作,具有完全顺序一致性排序。也就是说,a_x += 3 是一个原子操作。 - trent
1
是的...是的,我做到了。 - trent
显示剩余2条评论
1个回答

4
如果您想在非原子变量上使用原子操作,可以使用std::atomic_ref(C++20)。您可以在此处查看一个示例。
您的第二个示例应该没问题,因为a_x是具有memory_order_seq_cst内存模型的原子变量,并且+=已被定义为它的原子操作。

C语言中+=操作符也是如此:https://en.cppreference.com/w/c/language/operator_assignment。谢谢! - cmutex
1
@user3124390:它在C17标准中的6.5.16.2(3)处。顺便说一句,有一个(非规范性的)注释7.17.7.5(5)与此相矛盾,并表示它们不能保证原子性,但这似乎是一个错误,并在缺陷报告486中提到。 - Nate Eldredge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接