std::atomic;执行保证?
我知道 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编译器和处理器确保执行编程的操作是一个基本假设。这与 std::atomic 无关。
std::atomic
提供的保证是单个操作以原子方式发生。那么这意味着什么呢?
考虑两个线程 A 和 B,它们都递增相同的整数变量。此操作通常涉及读取整数、加 1 并写入结果(请注意,这只是一个示例,C++ 标准没有说明操作如何分解为原子步骤,因此我们不能根据标准)。
在这种情况下,我们将有“读取”、“添加一个”和“写入”步骤。对于每个线程,保证这些步骤按该顺序执行,但不能保证这些步骤如何交错。它可能是:
导致整数增加两次。
也可能
会导致整数仅增加一次。
因此,此实现将具有竞争条件。
为了摆脱这个问题,我们可以使用
std::atomic
而不是普通的int
来表示整数。std::atomic
实现了++
运算符,并且std::atomic<>
提供的保证是在此递增情况将自动发生。在示例中,这意味着步骤序列(读取、加一、写入)不会被另一个线程中断。仍然无法保证线程之间的执行顺序。因此,我们可以有
or
但其他组合是不可能的,并且在这两种情况下整数都会增加两次。因此不存在竞争条件。
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 whichstd::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:
which results in the integer being incremented twice.
It could also be
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 plainint
for the integer.std::atomic<int>
implements the++
operator and the guarantee whichstd::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
or
but other combinations will not be possible and in both cases the integer will be incremented twice. Thus there is no race condition.