谁能告诉我std::atomic<T>::is_lock_free()是不是像常量一样是静态的?让它是非静态的和/或非常量表达式对我来说没有任何意义。
为什么它一开始就没有像C++17's is_always_lock_free那样设计?
发布于 2019-11-12 18:06:12
正如cppreference上所解释的
除了std::atomic_flag之外,所有的原子类型都可以使用互斥锁或其他锁定操作来实现,而不是使用无锁的
原子指令。原子类型有时也可以是无锁的,例如,如果只有对齐的内存访问在给定的体系结构上自然是原子的,那么相同类型的未对齐的对象就必须使用锁。
C++标准建议(但不要求)无锁原子操作也是无地址的,即适用于使用共享内存的进程之间的通信。
正如其他许多人所提到的,std::is_always_lock_free可能就是您真正想要的。
编辑:为了澄清,C++对象类型有一个对齐值,该值将其实例的地址限制为只能是2的幂的特定倍数([basic.align])。这些对齐值是由实现为基础类型定义的,不需要等于类型的大小。它们也可以比硬件实际支持的更严格。
例如,x86 (主要)支持未对齐的访问。然而,你会发现大多数编译器都有针对x86的alignof(double) == sizeof(double) == 8,因为未对齐的访问有很多缺点(速度、缓存、原子性...)。但是例如#pragma pack(1) struct X { char a; double b; };或alignas(1) double x;允许你有“未对齐的”double,所以当cppreference谈到“对齐的内存访问”时,它大概是根据硬件类型的自然对齐来这样做的,而不是以一种与其对齐要求相矛盾的方式使用C++类型(可能是UB)。
这里有更多信息:What's the actual effect of successful unaligned accesses on x86?
也请查看下面@Peter Cordes的有洞察力的评论!
发布于 2019-11-12 18:05:27
is_lock_free依赖于实际的系统,不能在编译时确定。
相关解释:
原子类型有时也可以是无锁的,例如,如果只有对齐的内存访问在给定的体系结构上自然是原子的,那么相同类型的未对齐的对象就必须使用锁。
发布于 2019-11-12 21:30:39
我已经在我的Windows-PC上安装了Visual Studio 2019,这个devenv也有一个ARMv8编译器。ARMv8允许未对齐的访问,但比较和交换、锁定添加等必须是对齐的。此外,使用ldp或stp (32位寄存器的加载对或存储对)的纯加载/纯存储只有在它们自然对齐时才能保证是原子的。
因此,我编写了一个小程序来检查任意原子指针的is_lock_free()返回的值。下面是代码:
#include <atomic>
#include <cstddef>
using namespace std;
bool isLockFreeAtomic( atomic<uint64_t> *a64 )
{
return a64->is_lock_free();
}这是isLockFreeAtomic的反汇编
|?isLockFreeAtomic@@YA_NPAU?$atomic@_K@std@@@Z| PROC
movs r0,#1
bx lr
ENDP这只是returns true,又名1。
此实现选择使用alignof( atomic<int64_t> ) == 8,因此每个atomic<int64_t>都正确对齐。这避免了对每个加载和存储进行运行时对齐检查的需要。
(编者按:这很常见;大多数现实生活中的C++实现都是这样工作的。这就是std::is_always_lock_free如此有用的原因:因为它通常适用于is_lock_free()为真的类型。)
https://stackoverflow.com/questions/58816223
复制相似问题