为什么只有 std::atomic_flag 可以保证无锁?

Why only std::atomic_flag is guaranteed to be lock-free?

来自 C++ 并发实战:

difference between std::atomic and std::atomic_flag is that std::atomic may not be lock-free; the implementation may have to acquire a mutex internally in order to ensure the atomicity of the operations

我不知道为什么。如果保证 atomic_flag 是无锁的,为什么 atomic<bool> 也不能保证? 这是因为成员函数compare_exchange_weak?我知道有些机器缺少一个比较和交换指令,是这个原因吗?

首先,你完全可以拥有像 std::atomic<very_nontrivial_large_structure> 这样的东西,所以 std::atomic 这样的东西通常不能保证是无锁的(尽管对于像 [= 这样的琐碎类型的大多数特化12=] 或 int 可能在大多数系统上)。但这有点无关。

为什么 atomic_flag 而不是 必须 无锁的确切原因在 N2427/29.3 的注释中给出:

Hence the operations must be address-free. No other type requires lock-free operations, and hence the atomic_flag type is the minimum hardware-implemented type needed to conform to this standard. The remaining types can be emulated with atomic_flag, though with less than ideal properties.

换句话说,它是每个平台必须保证的最低限度的东西,所以正确执行标准是可能的。

标准不保证原子对象是无锁的。在不为 T 类型提供无锁原子操作的平台上,std::atomic<T> 对象可以使用互斥锁实现,这不是无锁的。在那种情况下,任何在其实现中使用这些对象的容器都不会是无锁的。

该标准提供了检查 std::atomic<T> 变量是否无锁的机会:您可以使用 var.is_lock_free()atomic_is_lock_free(&var)。对于 int 等基本类型,还提供了宏(例如 ATOMIC_INT_LOCK_FREE),用于指定对该类型的无锁原子访问是否可用。

std::atomic_flag 是原子布尔类型。对于 boolean 类型,几乎总是不需要使用互斥锁或其他同步方式。