简体   繁体   English

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

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

I think I mostly understand the semantics of the various memory_order flags in the C++ atomic library. 我想我最了解C ++原子库中各种memory_order标志的语义。

However, I'm confused about the following situation: 但是,我对以下情况感到困惑:

Suppose we have two threads - Thread A, which is a "main execution" thread, and Thread B, which is some arbitrary thread that is part of a thread pool where tasks can be scheduled and run. 假设我们有两个线程-线程A是一个“主执行”线程,而线程B是一个任意线程,它是可以调度和运行任务的线程池的一部分。

If I perform a "read-write-update" atomic operation using std::memory_order_acq_rel , then perform a non-atomic write on a boolean variable, is the non-atomic write immediately visible to other threads? 如果我执行“读-写更新”使用原子操作std::memory_order_acq_rel ,然后在一个布尔变量执行非原子写,就是非原子写入立即给其他线程可见? I would think the answer is no, unless the other threads also access the atomic variable that did the "read-write-update" operation. 我认为答案是否定的,除非其他线程也访问执行“读写更新”操作的原子变量。

So, for example, given a global std::atomic_flag variable X , a global bool value B, and a thread pool object THREADPOOL that has a member function dispatch , which will execute arbitrary function handlers in another thread: 因此,例如,给定全局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?
   });
}

So in this example, the code inside the lambda function will be executed in a different thread. 因此,在此示例中,lambda函数内部的代码将在其他线程中执行。 Is that thread necessarily going to see the (non-atomic) update to B made in the first thread? 该线程是否一定会看到在第一个线程中对B的(非原子的)更新? Note that the second thread does not access the atomic_flag, so my understanding is that changes to B will not necessarily be seen in the second thread. 需要注意的是第二个线程访问atomic_flag,所以我的理解是,改变B 不一定会在第二个线程看到。

Is my understanding correct here? 我的理解在这里正确吗? And if so, would using std::memory_order_seq_cst change that? 如果是这样,使用std::memory_order_seq_cst改变这一点吗?

Correct implementation of dispatch method in THREADPOOL should provide happens-before relation between all operations executed by the caller before this method call and all operations executed by the function(lambda in your case), passed to the method. THREADPOOL正确的dispatch方法THREADPOOL应在此方法调用之前由调用方执行的所有操作与传递给该方法的函数(由lambda执行)的所有操作之间提供happens-before关联。

So, auxiliary thread, executed your lambda function, will definitely see value of B , assigned by the main thread. 因此,执行您的lambda函数的辅助线程肯定会看到由主线程分配的B值。

Without happens-before order, the only way to garantee immediate visibility of variable modification is to use std::memory_order_seq_cst for both modification and reading. 没有先发生顺序,保证变量修改的即时可见性的唯一方法是使用std::memory_order_seq_cst进行修改和读取。 See, eg, this question . 参见例如这个问题

No memory order specification makes future memory accesses visible. 没有内存顺序规范可以使以后的内存访问可见。 At most, they prevent them from becoming visible before the atomic access is visible. 最多,它们阻止它们在可见原子访问之前就变得可见。

If you want to ensure a particular access does become visible, you must either enforce a particular memory ordering on that access or you must have a future access that uses memory ordering to ensure it is sequenced after the access you want to make visible. 如果要确保某个特定访问确实变得可见,则必须对该访问执行特定的内存排序,或者您必须拥有一个将来的访问,该访问使用内存排序来确保在要显示的访问之后对其进行排序。

All atomic operations are atomic. 所有原子操作都是原子的。 Memory ordering only allows you to do three things: 内存排序仅允许您执行三件事:

  1. Establish ordering of this atomic operation with respect to prior operations, atomic or not -- this operation is guaranteed to come after them. 相对于先前的操作(无论是否为原子操作)建立此原子操作的顺序-保证此操作在它们之后进行。

  2. Establish ordering of this operation with respect to future operations, atomic or not -- this operation is guaranteed to come before them. 相对于将来的操作(无论是否为原子操作)建立此操作的顺序-保证此操作先于它们进行。

  3. Establish ordering with other atomic operations. 与其他原子操作建立排序。

None of these ensure future non-atomic operations occur "soon" or become visible at any particular time. 这些都不保证未来的非原子操作“很快”发生或在任何特定时间可见。

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

相关问题 atomic_thread_fence(memory_order_release) 与使用memory_order_acq_rel 有什么不同? - Is atomic_thread_fence(memory_order_release) different from using memory_order_acq_rel? 为什么不使用 std::memory_order_acq_rel - Why not use std::memory_order_acq_rel memory_order_seq_cst 和 memory_order_acq_rel 有何不同? - How do memory_order_seq_cst and memory_order_acq_rel differ? 原子地读取非原子变量? - Read a non-atomic variable, atomically? C ++ 11使用非原子变量的原子内存顺序 - C++11 Atomic memory order with non-atomic variables 可以使用std :: atomic内存屏障在线程之间传输非原子数据吗? - Can std::atomic memory barriers be used to transfer non-atomic data between threads? 在c ++ 11中,可以使用std :: atomic在两个线程之间传输非原子数据 - in c++11, can std::atomic be used to transmit non-atomic data between two thread fetch_add 与 acq_rel 内存顺序 - fetch_add with acq_rel memory order std::atomic_ref 如何为非原子类型实现? - How is std::atomic_ref implemented for non-atomic types? C++ 线程安全:如果只有一个线程可以写入非原子变量但多个线程从中读取..会遇到问题吗? - C++ Thread Safety: If only one thread can write to a non-atomic variable but multiple threads read from it.. can problems be encountered?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM