原子SEQ_CST内存顺序如何实际工作?

发布于 2025-02-10 05:57:09 字数 746 浏览 2 评论 0原文

例如,有共享变量。

int val;
Cls obj;

原子bool变量充当数据指标。

std::atomic_bool flag = false;

线程1仅设置这些变量。

while (flag == true) { /* Sleep */ }

val = ...;
obj = ...;

flag = true; /* Set flag to true after setting shared variables. */

线程2仅获取这些变量。

while (flag != true) { /* Sleep */ }

int local_val = val;
Cls local_obj = obj;

flag = false; /* Set flag to false after using shared variables. */

我的问题是:

  1. 对于std :: memory_order_seq_cst,它的默认值为std :: atomic_bool,是否可以安全地在(...){}

  2. 使用bool而不是std :: atomic_bool是正确的吗?

For example, there are shared variables.

int val;
Cls obj;

An atomic bool variable acts as a data indicator.

std::atomic_bool flag = false;

Thread 1 only set these variables.

while (flag == true) { /* Sleep */ }

val = ...;
obj = ...;

flag = true; /* Set flag to true after setting shared variables. */

Thread 2 only get these variables.

while (flag != true) { /* Sleep */ }

int local_val = val;
Cls local_obj = obj;

flag = false; /* Set flag to false after using shared variables. */

My questions are:

  1. For std::memory_order_seq_cst, which is default for std::atomic_bool, is it safe to set or get shared variables after while (...) {}?

  2. Using bool instead of std::atomic_bool is correct or not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尸血腥色 2025-02-17 05:57:09
  1. 是的,代码很好,正如Alx23Z所说,如果所有flag的负载均为std :: memory_order_acquire,并且所有商店都是std :: memory_order_releasestd :: memory_order_seq_cst提供的额外语义仅与观察到两个或更多不同的原子变量之间的载荷和商店之间的排序有关。当您的整个程序只有一个原子变量时,它没有有用的效果。

    粗略地,想法是获得/发布足以确保对非原子变量的访问确实确实发生在Atomic flag之间,并且不泄漏”出去”。更正式的是,您可以使用C ++ 11内存模型公理来证明,鉴于线程1中对象的任何读取,并且在线程2中的任何写入对象,其中一个发生在另一个之前。细节有点乏味,但是关键的想法是,收购负载和发行商店正是您需要获得同步的<​​/em>,这就是您在两个操作之间发生的关系的方式 - 不同的线程。

  2. 否,如果您将atomic_bool替换为bool,则您的代码具有未定义的行为。然后,您将在不同的线程中读取和编写所有变量,而没有可能会创建同步的静音或原子变量,这就是数据竞赛的定义。

  1. Yes, the code is fine, and as ALX23z says, it would still be fine if all the loads of flag were std::memory_order_acquire and all the stores were std::memory_order_release. The extra semantics that std::memory_order_seq_cst provides are only relevant to observing the ordering between loads and stores to two or more different atomic variables. When your whole program only has one atomic variable, it has no useful effect.

    Roughly, the idea is that acquire/release suffice to ensure that the accesses to your non-atomic variables really do happen in between the load/store of the atomic flag, and do not "leak out". More formally, you could use the C++11 memory model axioms to prove that given any read of the objects in thread 1, and any write of the objects in thread 2, one of them happens before the other. The details are a little tedious, but the key idea is that an acquire load and a release store is exactly what you need to get synchronization, which is how you get a happens-before relation between operations in two different threads.

  2. No, if you replace the atomic_bool with a plain bool then your code has undefined behavior. You would then be reading and writing all your variables in different threads, with no mutexes or atomic variables that could possibly create synchronization, and that is the definition of a data race.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文