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 共享变量的值,因为没有内存栅栏.还是我说错了?
你是对的。正如您所指出的,有些用例(例如计数器)是可以的。
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 共享变量的值,因为没有内存栅栏.还是我说错了?
你是对的。正如您所指出的,有些用例(例如计数器)是可以的。