std::atomic<bool>执行保证?
std::atomic<bool> execution guarantee?
我知道 std::atomics 应该有明确定义的行为,但我找不到这个问题的易于理解的在线答案:做 std::atomic.load() 和 . store() 有执行保证吗?
如果两个线程尝试对同一个 std::atomic 对象进行并发写入或读取,是否保证写入和读取都被执行?换句话说,是否有可能写入或读取任务根本无法完成?一个或两个会被阻止吗?还是保证它们是按顺序排列的?我不是在这里询问操作顺序。我只是问是否会在未来某个未指定的时间完成手术。
编译器和处理器确保执行编程操作是一个基本假设。这与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
这将导致整数仅递增一次。
因此这个实现会有一个 race condition.
为了摆脱它,我们可以使用 std::atomic<int>
而不是普通的 int
作为整数。 std::atomic<int>
实现了 ++
运算符,std::atomic<>
提供的保证是在这种情况下递增将自动发生。
在该示例中,这意味着步骤序列 - 读取、加一、写入 - 不会被另一个线程中断。仍然无法保证线程之间的执行顺序。因此,我们可以
A: read
A: add1
A: write
B: read
B: add1
B: write
或
B: read
B: add1
B: write
A: read
A: add1
A: write
但其他组合是不可能的,在这两种情况下整数都会递增两次。因此没有竞争条件。
我知道 std::atomics 应该有明确定义的行为,但我找不到这个问题的易于理解的在线答案:做 std::atomic.load() 和 . store() 有执行保证吗?
如果两个线程尝试对同一个 std::atomic 对象进行并发写入或读取,是否保证写入和读取都被执行?换句话说,是否有可能写入或读取任务根本无法完成?一个或两个会被阻止吗?还是保证它们是按顺序排列的?我不是在这里询问操作顺序。我只是问是否会在未来某个未指定的时间完成手术。
编译器和处理器确保执行编程操作是一个基本假设。这与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
这将导致整数仅递增一次。
因此这个实现会有一个 race condition.
为了摆脱它,我们可以使用 std::atomic<int>
而不是普通的 int
作为整数。 std::atomic<int>
实现了 ++
运算符,std::atomic<>
提供的保证是在这种情况下递增将自动发生。
在该示例中,这意味着步骤序列 - 读取、加一、写入 - 不会被另一个线程中断。仍然无法保证线程之间的执行顺序。因此,我们可以
A: read
A: add1
A: write
B: read
B: add1
B: write
或
B: read
B: add1
B: write
A: read
A: add1
A: write
但其他组合是不可能的,在这两种情况下整数都会递增两次。因此没有竞争条件。