在原子加载之前使用获取栅栏

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

通常,在原子加载之后使用获取栅栏:

if (flag.load(std::memory_order_relaxed)) {
  std::atomic_thread_fence(std::memory_order_acquire);
  // Read some non-atomic data here.
}

但是,在原子加载之前使用获取栅栏是否有意义?

在下面的示例中,缓冲区

data

 和原子布尔标志在 
threadA
threadB
 之间共享。
data
 缓冲区最初包含全零。 
threadA
 将向其写入非零值,但在此之前,它将标志设置为 true。 
threadB
data
 缓冲区读取。读取后,它会检查原子标志。

#include <atomic> uint8_t data[4096] = {}; std::atomic<bool> flag = false; void threadA() { flag.store(true, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_release); for (uint8_t &byte : data) { byte = 1; } } void threadB() { bool found_non_zero = false; for (uint8_t byte : data) { if (byte) { found_non_zero = true; } } std::atomic_thread_fence(std::memory_order_acquire); bool flag_observed = flag.load(std::memory_order_relaxed); if (found_non_zero) { ASSERT_TRUE(flag_observed); } }
是否可以保证,如果

threadB

从缓冲区读取了任何非零数据,那么它必须观察到该标志被设置为true(即断言总是成功)?

希望

threadA

 中的释放栅栏可以防止将 
flag.store
 重新排序到写入 
data
 之后,并且 
threadB
 中的获取栅栏可以防止将 
flag.load
 重新排序到读取 
data
 之前.

但是,根据栅栏到栅栏同步的

标准,获取栅栏仅在原子加载之后出现时才有效;同样,释放栅栏仅在出现在原子存储之前时才有效。这表明 data

 应该是原子的,而标志不应该是原子的,这似乎是错误的。如果栅栏确实没有效果,那么对代码进行哪些修改才能确保断言始终成功?

c++ atomic memory-barriers lock-free memory-model
1个回答
0
投票
数据需要是原子的,并且需要通过发布来存储。

栅栏确保如果您在原子上看到一个观察(数据为 1),那么栅栏(标志)之后的其他非原子观察将至少与原子(数据)一样新。

你的代码有相反的情况。

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