std::atomic;执行保证?

发布于 2025-01-17 01:32:56 字数 251 浏览 2 评论 0原文

我知道 std::atomic 应该具有明确定义的行为,但我找不到这个问题的易于理解的在线答案:Do std::atomic.load() 和 .store() 有执行保证吗?

如果两个线程尝试对同一个 std::atomic 对象进行并发写入或读取,是否保证写入和读取都被执行?换句话说,写入或读取任务是否有可能根本无法完成?其中之一或两者会被阻止吗?或者它们保证是连续的?我不是在这里询问操作顺序。我只是简单地询问手术是否会在未来某个未指定的时间进行。

I know std::atomics are supposed to have well defined behavior, but I can't find an easy-to-digest online answer to this question: Do std::atomic.load() and .store() have execution guarantees?

If two threads attempt a concurrent write or read on the same std::atomic object, are both the write and read guaranteed to be executed? In other words, is it possible either the write or read task will simply not get done? Will one or both be blocked? Or are they guaranteed to be sequentialized? I am NOT asking here about order of operations. I am asking simply if the operation will be done at some unspecified time in the future.

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

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

发布评论

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

评论(1

我恋#小黄人 2025-01-24 01:32:56

编译器和处理器确保执行编程的操作是一个基本假设。这与 std::atomic 无关。 std::atomic 提供的保证是单个操作以原子方式发生。

那么这意味着什么呢?

考虑两个线程 A 和 B,它们都递增相同的整数变量。此操作通常涉及读取整数、加 1 并写入结果(请注意,这只是一个示例,C++ 标准没有说明操作如何分解为原子步骤,因此我们不能根据标准)。

在这种情况下,我们将有“读取”、“添加一个”和“写入”步骤。对于每个线程,保证这些步骤按该顺序执行,但不能保证这些步骤如何交错。它可能是:

   B: read
   B: add1
   B: write
   A: read
   A: add1
   A: write

导致整数增加两次。

也可能

   A: read
   A: add1
   B: read
   B: add1
   B: write
   A: write

会导致整数仅增加一次。

因此,此实现将具有竞争条件

为了摆脱这个问题,我们可以使用 std::atomic 而不是普通的 int 来表示整数。 std::atomic 实现了 ++ 运算符,并且 std::atomic<> 提供的保证是在此递增情况将自动发生。

在示例中,这意味着步骤序列(读取、加一、写入)不会被另一个线程中断。仍然无法保证线程之间的执行顺序。因此,我们可以有

   A: read
   A: add1
   A: write
   B: read
   B: add1
   B: write

or

   B: read
   B: add1
   B: write
   A: read
   A: add1
   A: write

但其他组合是不可能的,并且在这两种情况下整数都会增加两次。因此不存在竞争条件。

It is a basic assumption that the compiler and processor ensures that the programmed operations are executed. This has nothing to do with std::atomic<>. The guarantee which std::atomic<> offers is that single operations happen atomically.

So what does that mean?

Consider two threads, A and B, which both increment the same integer variable. This operation typically involves reading the integer, adding 1 and writing the result (notice that this is only an example, the C++ standard does not say anything about how operations are broken into atomic steps and thus we cannot make any assumptions about it based on the standard).

In this case we would have the steps "read", "add one" and "write". For each thread, these steps are guaranteed to the executed in that order, but there is no guarantee how the steps are interleaved. It may be:

   B: read
   B: add1
   B: write
   A: read
   A: add1
   A: write

which results in the integer being incremented twice.

It could also be

   A: read
   A: add1
   B: read
   B: add1
   B: write
   A: write

which would result in the integer being incremented only once.

Thus this implementation would have a race condition.

To get rid of that we can use a std::atomic<int> instead of a plain int for the integer. std::atomic<int> implements the ++ operator and the guarantee which std::atomic<> provides is that incrementing in this case will happen atomically.

In the example, this means that the sequence of steps - read, add one, write - will not be interrupted by another thread. There is still no guarantee about the order of execution between the threads. Hence, we could have

   A: read
   A: add1
   A: write
   B: read
   B: add1
   B: write

or

   B: read
   B: add1
   B: write
   A: read
   A: add1
   A: write

but other combinations will not be possible and in both cases the integer will be incremented twice. Thus there is no race condition.

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