繁体   English   中英

std :: memory_order_acq_rel对在其他线程中读取的非原子变量的影响

[英]Effect of std::memory_order_acq_rel on non-atomic variable read in other thread

我想我最了解C ++原子库中各种memory_order标志的语义。

但是,我对以下情况感到困惑:

假设我们有两个线程-线程A是一个“主执行”线程,而线程B是一个任意线程,它是可以调度和运行任务的线程池的一部分。

如果我执行“读-写更新”使用原子操作std::memory_order_acq_rel ,然后在一个布尔变量执行非原子写,就是非原子写入立即给其他线程可见? 我认为答案是否定的,除非其他线程也访问执行“读写更新”操作的原子变量。

因此,例如,给定全局std::atomic_flag变量X ,全局bool值B和具有成员函数dispatch的线程池对象THREADPOOL ,它将在另一个线程中执行任意函数处理程序:

if (!X.test_and_set(std::memory_order_acq_rel)
{
   if (SOME_CONDITION) B = true;
   THREADPOOL.dispatch([]() { 
      // This executes in Thread B
      if (B) { /* do something */ } // are we guaranteed to see changes to B?
   });
}

因此,在此示例中,lambda函数内部的代码将在其他线程中执行。 该线程是否一定会看到在第一个线程中对B的(非原子的)更新? 需要注意的是第二个线程访问atomic_flag,所以我的理解是,改变B 不一定会在第二个线程看到。

我的理解在这里正确吗? 如果是这样,使用std::memory_order_seq_cst改变这一点吗?

THREADPOOL正确的dispatch方法THREADPOOL应在此方法调用之前由调用方执行的所有操作与传递给该方法的函数(由lambda执行)的所有操作之间提供happens-before关联。

因此,执行您的lambda函数的辅助线程肯定会看到由主线程分配的B值。

没有先发生顺序,保证变量修改的即时可见性的唯一方法是使用std::memory_order_seq_cst进行修改和读取。 参见例如这个问题

没有内存顺序规范可以使以后的内存访问可见。 最多,它们阻止它们在可见原子访问之前就变得可见。

如果要确保某个特定访问确实变得可见,则必须对该访问执行特定的内存排序,或者您必须拥有一个将来的访问,该访问使用内存排序来确保在要显示的访问之后对其进行排序。

所有原子操作都是原子的。 内存排序仅允许您执行三件事:

  1. 相对于先前的操作(无论是否为原子操作)建立此原子操作的顺序-保证此操作在它们之后进行。

  2. 相对于将来的操作(无论是否为原子操作)建立此操作的顺序-保证此操作先于它们进行。

  3. 与其他原子操作建立排序。

这些都不保证未来的非原子操作“很快”发生或在任何特定时间可见。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM