![](/img/trans.png)
[英]Why isn't std::atomic_is_lock_free a static constexpr?
[英]Why is std::atomic<T>::is_lock_free() not static as well as constexpr?
誰能告訴我 std::atomic::is_lock_free() 不是 static 和 constexpr 嗎? 讓它非靜態和/或非 constexpr 對我來說沒有意義。
如cppreference中所述:
除了 std::atomic_flag 之外的所有原子類型都可以使用互斥鎖或其他鎖定操作來實現,而不是使用無鎖原子 CPU 指令。 原子類型有時也可以是無鎖的,例如,如果僅對齊的 memory 訪問在給定架構上自然是原子的,則相同類型的未對齊對象必須使用鎖。
C++ 標准建議(但不要求)無鎖原子操作也是無地址的,即適用於使用共享 memory 的進程之間的通信。
正如其他人所提到的, std::is_always_lock_free
可能是您真正想要的。
編輯:澄清一下,C++ object 類型具有 alignment 值,該值將其實例的地址限制為僅是 2 的某些冪的倍數( [basic.align]
)。 這些 alignment 值是針對基本類型的實現定義的,不需要等於類型的大小。 它們也可能比硬件實際支持的更嚴格。
例如,x86(大部分)支持非對齊訪問。 但是,您會發現大多數編譯器對於 x86 具有alignof(double) == sizeof(double) == 8
,因為未對齊的訪問有許多缺點(速度、緩存、原子性......)。 但是例如#pragma pack(1) struct X { char a; double b; };
#pragma pack(1) struct X { char a; double b; };
或alignas(1) double x;
允許您擁有“未對齊”的double
s。 So when cppreference talks about "aligned memory accesses", it presumably does so in terms of the natural alignment of the type for the hardware, not using a C++ type in a way that contradicts its alignment requirements (which would be UB).
這里有更多信息: 成功的非對齊訪問對 x86 的實際影響是什么?
還請查看下面@Peter Cordes的富有洞察力的評論!
is_lock_free
取決於實際系統,無法在編譯時確定。
相關解釋:
原子類型有時也可以是無鎖的,例如,如果僅對齊的 memory 訪問在給定架構上自然是原子的,則相同類型的未對齊對象必須使用鎖。
我已經在我的 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>
都正確對齊。 這避免了運行時 alignment 檢查每次加載和存儲的需要。
(編者注:這很常見;大多數現實生活中的 C++ 實現都是這樣工作的。這就是std::is_always_lock_free
如此有用的原因:因為它通常適用於is_lock_free()
永遠為真的類型。)
std::atomic<T>::is_lock_free()
在某些實現中可能會根據運行時條件返回true
或false
。
正如 Peter Cordes 在評論中指出的那樣,運行時條件不能是 alignment,因為原子會(過度)對齊內部存儲以實現高效的無鎖操作,而強制不對齊是 UB,可能表現為原子性的喪失。
運行時條件可能決定原子性的實際原因是運行時 CPU 調度。
在 x86-64 上,實現可以在初始化時通過cpuid
檢測cmpxchg16b
的存在,並將其用於 128 位原子,這同樣適用於cmpxchg8b
和 32 位上的 64 位原子。 如果沒有找到對應的cmpxchg
,則 lock-free atomic 是無法實現的,並且該實現使用了鎖。
MSVC 目前不執行運行時 CPU 調度。 由於 ABI 兼容性原因,它不會為 64 位執行此操作,並且不會為 32 位執行此操作,因為它已經不支持沒有cmpxchg8b
的 CPU。 默認情況下,Boost.Atomic 不執行此操作(假設cmpxchg8b
和cmpxhg16b
存在),但可以配置用於檢測。 我還沒有費心去看看其他實現是做什么的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.