gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:18:08 26 4
gpt4 key购买 nike

我正在研究这个网站: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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com