两个原子加载之间的重新排序

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

我有以下程序:

int normalData[2];
std::atomic<int> counter {0};

// thread A:
// write new data
normalData[(counter + 1) % 2] = newData;
counter.fetch_and_add(1, std::memory_order_release);

// thread B:
auto before = counter.load(std::memory_order_acquire);
auto tmp = normalData[before % 2];
auto after = counter.load(?);
bool success = (before == after);

每当线程 A 写入新值时,计数器就会递增。

std::memory_order_release
确保在计数器递增之前数据已被写入。另一方面,线程 B 想要读取数据并用
std::memory_order_acquire
加载计数器。这保证了在线程A写入数据之前无法开始读取数据。到目前为止一切正常。但为了查看读取的数据是否有效,计数器会被第二次加载。但是如何防止在实际读取数据之前执行第二次加载呢?通常第二个负载必须有
std::memory_order_release
,这是禁止进行负载操作的。那么我怎样才能防止代码被重新排序为:

// thread B:
auto before = counter.load(std::memory_order_acquire);
auto after = counter.load(?);
auto tmp = normalData[before % 2];
bool success = (before == after);
c++ memory-barriers stdatomic
1个回答
0
投票

std::memory_order_acquire
,如cppreference所述,确保“在此加载之前当前线程中的任何读取或写入都不能重新排序”,并且:“释放相同原子变量的其他线程中的所有写入在当前线程”,所以
std::memory_order_acquire
就是您正在寻找的内容。

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