假设我们有2个主题。一个生产者和一个消费者。我们有生产数据的生产者和使用这些数据的消费者。然而,守卫不是原子的!
bool isDataReady = false;
int data = 0;
void Producer() {
data = 42;
std::atomic_thread_fence(std::memory_order_release);
isDataReady = true;
}
void Consumer() {
while(!isDataReady);
std::atomic_thread_fence(std::memory_order_acquire);
assert(data == 42);
}
我想知道为什么isDataReady
会有数据竞争。通常,正确的代码应该是在原子bool变量上使用relaxed
排序。
是因为isDataReady的write(事务)可能在读取之前没有完成吗?即使是这样,它真的是一个问题吗?
这种数据竞争是危险的,您应该关心消除它。它可能不会因你的运气而显现,但它最终会引起头痛。
由于一些问题,此代码存在问题:
Consumer
编译器并不知道isDataReady
可以在背景中改变,所以将while(!isDataReady)
发出无限循环或者什么都没有是完全合理的(由于forward progress guarantee,正如评论中指出的那样)。bool
的写入和/或读取不是原子的(在大多数平台上都不是这种情况,但理论上是可行的)任何读取都可能导致获取垃圾数据。std::memory_order_release
的内存栅栏可确保在其他线程使用std::memory_order_acquire
调用fence之后可以看到线程中发生的更改(至少在简化中)。因此,bool变量的变化在其他线程中可能是不可见的。Producer
可见的Consumer
中的内存写入顺序可能与放在代码中的顺序不同。