簡體   English   中英

為什么 std::atomic<t> ::is_lock_free() 不是 static 和 constexpr?</t>

[英]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的富有洞察力的評論!

您可以使用std::is_always_lock_free

is_lock_free取決於實際系統,無法在編譯時確定。

相關解釋:

原子類型有時也可以是無鎖的,例如,如果僅對齊的 memory 訪問在給定架構上自然是原子的,則相同類型的未對齊對象必須使用鎖。

我已經在我的 Windows-PC 上安裝了 Visual Studio 2019,這個 devenv 也有一個 ARMv8 編譯器。 ARMv8 允許非對齊訪問,但比較和交換、鎖定添加等都必須對齊。 而且,使用ldpstp (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()在某些實現中可能會根據運行時條件返回truefalse

正如 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 不執行此操作(假設cmpxchg8bcmpxhg16b存在),但可以配置用於檢測。 我還沒有費心去看看其他實現是做什么的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM