首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::memory_order_acq_rel对其它线程非原子变量读取的影响

std::memory_order_acq_rel对其它线程非原子变量读取的影响
EN

Stack Overflow用户
提问于 2015-06-29 17:26:37
回答 2查看 240关注 0票数 0

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

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

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

如果我使用std::memory_order_acq_rel执行“读-写-更新”原子操作,那么对布尔变量执行非原子写入,其他线程会立即看到非原子写入吗?我认为答案是否定的,除非其他线程也访问执行“读-写-更新”操作的原子变量。

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

代码语言:javascript
复制
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会改变这一点吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-29 19:44:51

dispatch方法在THREADPOOL中的正确实现应该提供调用方在此方法调用之前执行的所有操作与传递给该方法的函数(在您的示例中为lambda)执行的所有操作之间的happens-before关系。

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

没有发生-在顺序之前,确保变量修改的可见性的唯一方法是使用std::memory_order_seq_cst进行修改和读取。参见,例如,this question

票数 3
EN

Stack Overflow用户

发布于 2015-06-29 18:21:30

没有内存顺序规范使未来的内存访问可见。充其量,它们可以防止它们在原子访问可见之前变得可见。

如果要确保特定访问确实可见,则必须对该访问强制执行特定的内存排序,或者必须具有使用内存排序的未来访问权限,以确保在要使访问可见后对其进行排序。

所有原子操作都是原子操作。内存排序只允许您做三件事:

  1. 建立这个原子操作相对于以前的操作的顺序,原子操作或非原子操作--这个操作保证在它们之后出现。
  2. 根据未来的操作,无论是原子操作还是非原子操作,建立这个操作的顺序--这个操作保证会出现在它们之前。
  3. 与其他原子操作建立顺序。

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31121876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档