c++ - 对原子类 : memory_order_relaxed 感到困惑

标签 c++ multithreading thread-safety atomic memory-model

我正在研究这个网站:https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync ,这对理解关于原子类的话题非常有帮助。

但是这个放松模式的例子很难理解:

    /*Thread 1:*/

    y.store (20, memory_order_relaxed)
    x.store (10, memory_order_relaxed)
    /*Thread 2*/
 if (x.load (memory_order_relaxed) == 10)
      {
        assert (y.load(memory_order_relaxed) == 20) /* assert A */
        y.store (10, memory_order_relaxed)
      }
 /*Thread 3*/
     if (y.load (memory_order_relaxed) == 10)
        assert (x.load(memory_order_relaxed) == 10) /* assert B */

对我来说断言 B 永远不会失败,因为 x 必须是 10 并且 y=10 因为线程 2 已经以此为条件。

但是网站上说这个例子中的任何一个断言实际上都可能失败。

最佳答案

To me assert B should never fail, since x must be 10 and y=10 because of thread 2 has conditioned on this.

实际上,您的论点是因为在线程 2 中将 10 存储到 x 发生在将 10 存储到 y 之前,因此在线程 3 中必须是情况。

但是,由于您仅使用宽松的内存操作,因此代码中没有任何内容需要两个不同的线程就不同 变量的修改之间的顺序达成一致。因此,实际上线程 2 可能会先将 10 存储到 x,然后再将 10 存储到 y,而线程 3 会以相反的顺序看到这两个操作。

为了确保断言 B 成功,您实际上需要确保当线程 3 看到 y 的值 10 时,它还会看到该线程执行的任何其他副作用在存储时间之前将 10 存储到 y 中。也就是说,您需要将 10 存储到 y 中以同步y 加载 10。这可以通过让存储执行释放并让负载执行获取来完成:

// thread 2
y.store (10, memory_order_release);

// thread 3
if (y.load (memory_order_acquire) == 10)

释放操作与读取存储值的获取操作同步。现在因为线程 2 中的存储与线程 3 中的加载同步,线程 3 中加载之后发生的任何事情都会看到线程 2 中存储之前发生的任何事情的副作用。因此断言将成功。

当然,我们还需要确保断言A成功,方法是让线程1中的x.store使用release,线程2中的x.load使用获取。

关于c++ - 对原子类 : memory_order_relaxed 感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46065770/

相关文章:

c# - CultureInfo线程安全

c++ - OnDestroy 中的 DestroyWindow 不起作用

c++ - 换显卡后需要重新安装cuda吗

c++ - 线程间实时数据共享

java - Java 同步方法入口点线程是否足够安全?

java - 局部变量同步,比同步方法更好?

c++ - DBus与其他进程间通信方式的区别

c++ - 在较大字符串中查找子字符串的查找方法

multithreading - Spring 批处理 : problems (mix data) when converting to multithread

python - 找到目标后如何停止线程?