![](/img/trans.png)
[英]Atomic exchange of two std::atomic<T*> objects in a lock-free manner in C++11?
[英]Why don't standard libraries implement std::atomic for structs under 8 bytes in a lock-free manner?
假設該體系結構可以為std :: atomic以無鎖方式支持8字節標量。 為什么標准庫不為8字節以下的結構提供類似的特化?
這種std :: atomic特化的簡單實現只能將結構序列化/反序列化(使用std::memcpy
)到等效的std::uintx_t
,其中x
是結構的寬度(以位為單位)(舍入為最接近的冪) 2大於或等於結構的寬度)。 這將被很好地定義,因為std :: atomic需要這些結構是可以輕易復制的。
例如。 https://godbolt.org/z/sxSeId ,這里Something
只有3個字節,但實現調用__atomic_load
和__atomic_exchange
,兩者都使用鎖表。
使用struct Something { alignas(4) char a; char b,c; };
struct Something { alignas(4) char a; char b,c; };
(不是alignas(4) char a,b,c;
因為這會使每個 char填充為4個字節,因此它們可以各自對齊。)
具有非2次冪大小的對象可能跨越高速緩存行邊界,因此使用更寬的4字節負載並不總是可行的。
加上純商店總是必須使用CAS(例如lock cmpxchg
)來避免發明寫入對象外的字節:顯然你不能使用兩個單獨的mov
存儲(2字節+ 1字節),因為這不會是原子的,除非你在帶有重試循環的TSX事務中這樣做。
對於不跨越8字節邊界的內存訪問,x86加載/存儲僅保證原子性。 (在一些供應商/搜索中,緩存行邊界。或者對於可能不可緩存的加載/存儲,基本上自然對齊是您需要的)。 為什么在x86上對自然對齊的變量進行整數賦值?
你的struct Something { char a, b, c; };
struct Something { char a, b, c; };
沒有對齊要求所以沒有C ++規則阻止Something
對象跨越2個緩存行。 這將使個純mov
它加載/存儲絕對非原子。
gcc和鐺選擇實現atomic<T>
用相同的布局/對象的表示為T
(無論是無鎖的或沒有)。 因此, atomic<Something>
是一個3字節的對象。 因此, atomic<Something>
的數組必然會有一些跨越緩存行邊界的對象,並且不能在對象外部填充,因為這不是數組在C中的工作方式sizeof()
= 3告訴您數組布局。 這使得無鎖atomic<Something>
變得不可能。 (除非你使用lock cmpxchg
加載/存儲即使在緩存行拆分時也是原子的,否則會在發生這種情況時產生巨大的性能損失。更好地讓開發人員修復它們的結構。)
atomic<T>
類可以具有比T
更高的對齊要求,例如atomic<int64_t>
具有alignof(atomic_int64_t)== 8,與許多32位平台(包括i386 System V alignof(int64_t) == 4
上的alignof(int64_t) == 4
不同ABI)。
如果gcc / clang沒有選擇保持布局相同,那么他們可能有atomic<T>
墊小對象,直到2的下一個冪並添加對齊,這樣它們就可以無鎖。 這將是一個有效的實現選擇。 我想不出任何缺點。
有趣的是,gcc的C11 _Atomic
支持在具有64位無鎖原子的32位平台上略有破壞 : _Atomic _Atomic int64_t
可能在結構內部未對齊導致撕裂。 他們仍然沒有更新_Atomic
類型的ABI以具有自然對齊。
但是g ++的C ++ 11 std :: atomic在一個標題中使用了一個模板類來修復那個bug( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65147 ); 確保atomic<T>
具有自然對齊(最大為2個大小的冪),即使T
具有對齊<大小。 因此,他們無法跨越任何邊界。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.