放宽顺序作为信号

relaxed ordering as a signal

假设我们有两个线程。一个给出一个 "go" 一个等待产生一些东西。

此代码是否正确,或者我可以因为缓存或类似原因而拥有 "infinite loop" 吗?

std::atomic_bool canGo{false};

void producer() {
    while(canGo.load(memory_order_relaxed) == false);
    produce_data();
}

void launcher() {
    canGo.store(true, memory_order_relaxed);
}

int main() {
    thread a{producer};
    thread b{launcher};
}

如果这段代码不正确,有没有办法在标准 c++ 中刷新/使缓存失效?

像这样的开始信号通常会响应您希望目标看到的一些内存变化。

换句话说,您通常希望为此类信号提供 release/acquire 语义。

这可以通过在商店上使用 memory_order_release 并在负载上使用 memory_order_acquire 来完成,或者通过放置 release 栅栏 before 宽松的存储和 acquire fence after 宽松的负载,以便信号器在存储之前完成内存操作信号接收者可见(例如,参见 https://preshing.com/20120913/acquire-and-release-semantics/ 或 C/C++ 标准)。


我记得栅栏的排序方式是,据我所知,内核之间的共享内存操作是有效的 hardware implemented buffered IO that follows a protocol, 并且释放栅栏应该有点像输出缓冲区刷新和像输入缓冲区一样获取栅栏 flush/sync.

现在,如果您在发布宽松存储之前刷新核心的内存操作输出缓冲区,那么当目标核心看到宽松存储时,前面的内存操作消息必须可用它和它在其内存中看到这些内存更改所需要做的就是在看到信令存储后将它们与获取栅栏同步。