是否可以保证读取-修改-写入操作在弱内存模型上读取(并返回)正确的旧值?

问题描述 投票:0回答:1

假设我有以下代码,它利用 RMW 操作,并在 WMM CPU 上执行(例如,在 ARM 上):

std::atomic<int> shared;

std::atomic<bool> t0_is_last;
std::atomic<bool> t1_is_last;

void t0() {
    int result0 = shared.fetch_or(1 << 0, std::memory_order_relaxed);
    if (result == (1 << 1)) { 
        t0_is_last.store(true, std::memory_order_relaxed); 
    }
}

void t1() {
    int result1 = shared.fetch_or(1 << 1, std::memory_order_relaxed);
    if (result == (1 << 0)) { 
        t1_is_last.store(true, std::memory_order_relaxed);
    }
}

这里,两个线程

t0
t1
尝试使用宽松的内存排序来
fetch_or
相同的变量。如果其中一个线程发现它是最后一个成功执行
fetch_or
操作的线程,那么它会将
true
与宽松的内存排序存储到它的标志,也就是说,以下线程是最后一个
fetch_or
变量
shared 
(标志
t0_is_last
t1_is_last
)。

那么,是否只有一个线程(不是零个或两个线程)可以修改其

tX_is_last
变量? 换句话说:在
t0
t1
完成之后,以下内容是否成立:
t0 ^ t1

或者换句话说:读-修改-写返回的值是否存在于系统中完全在写操作之前(正是被修改的值)

c++ caching arm memory-barriers stdatomic
1个回答
0
投票

处理器架构并不重要。

当您编写 C++ 代码时,您是在针对 C++ 的内存模型进行编写,而不是针对您正在编译的体系结构的内存模型。编译器有责任将 C++ 内存模型中的 C++ 代码语义转换为与架构内存模型相关的适当指令,以便可观察的行为与 C++ 在其抽象机上所需的行为相同。

C++ 的内存模型保证每个原子变量都有一个所有修改的总顺序。 RMW 操作(例如

fetch_or
)保证返回紧接在此修改顺序中的操作完成的修改之前的值。

因此,假设您打算将

shared
初始化为
0
(您目前忘记了),那么第一个线程的
fetch_or
在修改顺序中排在第一位,存储
0
,而第二个线程的
fetch_or因此 
必须读取
0
,否则第二个线程先出现,存储
1
,第一个线程的
fetch_or
读取
1

所以,是的,其中一个

tX_is_last
存储将会发生(假设程序中没有对
shared
进行任何进一步的修改)。

© www.soinside.com 2019 - 2024. All rights reserved.