c++ - 放宽顺序作为信号

标签 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};
}

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

最佳答案

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

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

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


我记得栅栏的顺序是,据我所知,内核之间的共享内存操作实际上是 hardware implemented buffered IO that follows a protocol,释放栅栏应该类似于输出缓冲区刷新,而获取栅栏类似于输入缓冲区刷新/同步。

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

关于c++ - 放宽顺序作为信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56906486/

相关文章:

C++ 我的表单应该位于各种窗口之上

c++ - 从 Linux OMI (omicli) 到 Windows WMI 的连接失败并出现 DMTF 相关错误

c# - 通过Process.Start()从多个线程启动可执行文件

c++ - 是什么保证弱松弛的无竞争 CAS 循环终止?

java - 如何用Java编写原子函数?

c++ - Eclipse C/C++ 显示错误但编译?

c++ - 在 Arch Linux 中使用 c++ Boost 正则表达式库

java - Runnable run() 函数立即终止

ruby-on-rails - jRuby with Rails 4的好处

multithreading - 无锁有界 MPMC 环形缓冲区故障