放宽排序作为信号

Ant*_*ier 5 c++ multithreading atomic memory-barriers

假设我们有两个线程。一个给出“去”,一个等待去生产一些东西。

这段代码是正确的还是我可以因为缓存或类似的东西而有一个“无限循环”?

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};
}
Run Code Online (Sandbox Code Playgroud)

如果此代码不正确,是否有办法在标准 C++ 中刷新/使缓存无效?

PSk*_*cik 5

像这样的 go 信号通常是为了响应您希望目标看到的一些内存变化。

换句话说,您通常希望为此类信号提供释放/获取语义。

这可以通过memory_order_release在存储和memory_order_acquire加载上使用来完成,或者通过在轻松存储之前放置一个释放栅栏并在轻松加载之后放置一个获取栅栏来完成,以便信号者在存储之前执行的内存操作对被信号者可见(例如,参见https://preshing.com/20120913/acquire-and-release-semantics/或 C/C++ 标准)。


我记得栅栏的顺序是,据我所知,内核之间的共享内存操作是有效的硬件实现的缓冲 IO,它遵循协议,而释放栅栏应该有点像输出缓冲区刷新和获取像输入缓冲区刷新/同步一样的栅栏。

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

  • @AntoineMorrier 那么你不需要栅栏。 (2认同)