memory_order_relaxed 的使用

Uses of memory_order_relaxed

Whosebug 上已经有一些问题本质上是询问 memory_order_relaxed 的用例,例如:

What are some use cases for memory_order_relaxed

但是,我仍然对 memory_order_relaxed 的精确语义感到困惑。通常,memory_order_relaxed 的示例用例类似于 std::shared_ptr - 基本上它保留一个原子计数器,但不需要与其他线程同步。

好的,那么我的理解是这样的:

std::memory_order_relaxed,当与 load() 一起使用时,仅保证加载它的线程将以原子方式执行 - 它不保证相对于执行 [=18= 的其他线程的任何顺序] 对同一个变量的操作,它绝对不保证任何 loads/stores 非原子变量(即不会生成内存栅栏。)

但是 memory_order_relaxed 是否提供任何类型的 "happens-before" 类型排序能力,关于 单个原子值?例如,如果我们有:

std::atomic_flag x = ATOMIC_FLAG_INIT;

// Thread A:
//
if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread A got here first!" << std::endl;
}

// Thread B:
//
if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread B got here first!" << std::endl;
}

在上面的例子中,即使我们使用了memory_order_relaxed,我们不是也提供了一种有保证的方式来推理这里的排序吗?换句话说,线程 A 和线程 B 都可以推断出哪个线程首先设置了标志。只是,由于顺序松散,线程 A 和线程 B 都不能假设任何周围 non-atomic 共享变量的值,因为没有内存栅栏.还是我说错了?

你是对的。正如您所指出的,有些用例(例如计数器)是可以的。