为什么std :: atomic <T> :: is_lock_free()和constexpr一样不是静态的?

Bon*_*ero 8 c++ multithreading std lock-free stdatomic

谁能告诉我std :: atomic :: is_lock_free()是否像constexpr一样不是静态的?使它为非静态和/或为非constexpr对我来说没有意义。

Max*_*hof 9

如对cppreference的解释:

除std :: atomic_flag以外的所有原子类型都可以使用互斥锁或其他锁定操作来实现,而不是使用无锁原子CPU指令来实现。原子类型有时也可以是无锁的,例如,如果在给定的体系结构上,只有对齐的内存访问自然是原子的,则相同类型的未对齐对象必须使用锁。

C ++标准建议(但不要求)无锁原子操作也无地址,也就是说,适用于使用共享内存的进程之间的通信。

正如其他许多人提到的那样,std::is_always_lock_free可能正是您真正想要的。


编辑:明确起见,C ++对象类型具有一个对齐值,该对齐值将其实例的地址限制为仅2的幂的某些倍数[basic.align]。这些对齐值是针对基本类型的实现定义的,不需要等于类型的大小。它们也可能比硬件实际支持的条件更严格。

例如,x86(大多数情况下)支持不对齐的访问。但是,您会发现大多数alignof(double) == sizeof(double) == 8x86 编译器都具有x86,因为未对齐的访问具有许多缺点(速度,缓存,原子性...)。但是,例如#pragma pack(1) struct X { char a; double b; };alignas(1) double x;允许您具有“ unaligned” double。因此,当cppreference谈论“对齐的内存访问”时,大概是根据硬件类型的自然对齐方式来进行的,而不是以与其对齐要求(即UB)相抵触的方式使用C ++类型。

这是更多信息:在x86上成功进行未对齐访问的实际影响是什么?

还请在下面查看@Peter Cordes的有见地的评论!

  • 但是,C++20 `std::atomic_ref<double>` 的正确实现要么完全拒绝未对齐的 `double`,要么在运行时在纯 `double` 和 `int64_t` 合法的平台上检查对齐情况。小于自然对齐。(因为 `atomic_ref<T>` 对声明为普通 `T` 的对象进行操作,并且仅具有 `alignof(T)` 的最小对齐方式,而没有机会为其提供额外的对齐方式。) (2认同)
  • 请参阅 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62259 了解现已修复的 libstdc++ 错误,以及 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65146 了解仍然存在的 C 错误,包括一个纯 ISO C11 测试用例,该测试用例显示使用当前的“gcc -m32”编译时“_Atomic int64_t”的撕裂。不管怎样,我的观点是,真正的编译器不支持未对齐的原子,并且不进行运行时检查(还?),所以 **`#pragma pack` 或 `__attribute__((packed))` 只会导致非原子性;对象仍然会报告它们是“lock_free”。** (2认同)

dar*_*une 4

您可以使用std::is_always_lock_free

is_lock_free取决于实际系统,无法在编译时确定。

相关解释:

原子类型有时也可以是无锁的,例如,如果在给定的体系结构上只有对齐的内存访问自然是原子的,则相同类型的未对齐对象必须使用锁。

  • `std::numeric_limits<int>::max` 取决于架构,但它是静态的并且 `constexpr`。我认为答案没有任何问题,但我不相信第一部分的推理 (2认同)