Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不使用std::内存\u顺序\u acq\u rel_C++_Multithreading_C++11_Atomic_Memory Model - Fatal编程技术网

C++ 为什么不使用std::内存\u顺序\u acq\u rel

C++ 为什么不使用std::内存\u顺序\u acq\u rel,c++,multithreading,c++11,atomic,memory-model,C++,Multithreading,C++11,Atomic,Memory Model,我最近正在学习CPPCRO项目的代码。我有个问题 使用第218行中的内存顺序释放写入,使用内存顺序获取标志的m_refCount可以在第284行中正确加载值。没关系。但是fetch_sub是RMW操作。要正确读取第284行中的修改,是否还需要内存顺序获取标志?所以我想知道为什么m_refCount不在第218行和第284行中使用memory_order_acq_rel return m_refCount.fetch_sub(1, std::memory_order_acquire) != 1

我最近正在学习CPPCRO项目的代码。我有个问题

使用第218行中的内存顺序释放写入,使用内存顺序获取标志的m_refCount可以在第284行中正确加载值。没关系。但是fetch_sub是RMW操作。要正确读取第284行中的修改,是否还需要内存顺序获取标志?所以我想知道为什么m_refCount不在第218行和第284行中使用memory_order_acq_rel

return m_refCount.fetch_sub(1, std::memory_order_acquire) != 1; // #284

谢谢。

对原子变量本身的操作不会以任何方式导致数据争用


std::memory\u order\u release
意味着所有修改的缓存数据都将提交到共享内存/RAM。内存顺序操作生成内存围栏,以便其他对象可以正确地提交到共享内存或从共享内存读取。

,因为内存顺序不是这样工作的

为了实现两个目标,我们在原子操作中添加了一个内存屏障:

  • 防止放松的原子操作和非原子操作被重新排序
  • 跨线程同步非原子数据
  • 我写了一个答案,更清楚地解释了这两点

    当一个协程在一个线程中挂起,在另一个线程中恢复时,不需要额外的同步*,表示:

    请注意,因为在进入waiter.wait_suspend()之前协程是完全挂起的,所以该函数可以自由地跨线程传输协程句柄,而无需额外的同步

    至于重新订购?实际逻辑(
    waterer->m_waiter.resume();
    )被一个大的if语句包围。无论如何,编译器都不能在
    fetch_sub
    之前对恢复进行重新排序,因为这样会忽略if语句的作用,并破坏代码的逻辑

    所以,我们不需要任何其他的记忆顺序,但要放松。事实上,
    fetch_XXX
    是一个RMW操作,这并不意味着什么——我们对正确的用例使用正确的内存顺序

    如果你喜欢cppcoro,请尝试我自己的coroutine库

    *更正确的说法是:除了从一个线程传递
    coroutine\u句柄所需的同步之外,不需要额外的同步
    
    另一个。

    内存顺序不会改变所讨论对象的原子性,它们只会放松其他对象的“先发生后发生”规则。您可以通过讨论缓存一致性来改进。您所说的“RAM”是什么意思?物理RAM模块?读了这篇文章后,我了解到您在上面的链接中写道:“使用原子变量可以解决问题-通过使用原子,所有线程都可以保证读取最新的写入值,即使内存顺序是放松的。”我对内存\u顺序\u放松标志有一些误解。我曾经认为原子变量使用内存、顺序和松弛标志。在B线程中读取时,不能保证及时发现A线程的写入操作。请再次读取链接的答案,这是一个常见的误解。同样,原子变量总是线程安全的。MO用于同步非原子数据并防止重新排序。原子变量不需要MO就可以是线程安全的。emm。。但仅仅谈论线程安全并不能解决我之前的疑问。我知道原子变量提供的线程安全性在于它不会读取正在更改的中间值。线程B无法及时发现线程A中的值更新,因此,由于缓存或其他类似原因,我认为这不是线程安全问题,而是内存可见性问题。所以我过去认为立即有效的可见性是由某个MO提供的,但我不知道它是由原子变量self提供的。
    return m_refCount.fetch_sub(1, std::memory_order_acquire) != 1; // #284