[英]std::map<int, std::bitset<256 > > thread safety w/o mutex?
我有一個
std::map<int, std::bitset<256 > > m;
施工后不會插入新鑰匙,也不會移除任何鑰匙。 我可以在不使用互斥鎖的情況下在一個線程中安全地分配位集,同時在其他線程中讀取它嗎?
// thread 1:
std::bitset<256> a = getBitset();
m[1] = a;
// thread 2:
std::bitset<256> b = m[1];
// or alternatively
std::bitset<256> c = m.at(1);
我認為該程序不會崩潰,但位集中可能會發生數據競爭。 如果讀取將提供新舊位集的組合,則數據競爭是可以接受的。
不,這不安全。
bitset
的operator=
是修改操作,因此如果在另一個線程中同時訪問bitset
,則不能保證不會發生數據競爭。 在實踐中,它幾乎肯定會導致數據競爭,因為它需要寫入 object。這不是特定於std::bitset
,但對於幾乎所有非空非原子標准庫類型(和大多數其他非空類型)。
任何數據競爭都會導致未定義的行為。 沒有部分更新。 從這個意義上說,它永遠不應該被接受。
如果你希望能夠做到這一點,要么將bitset
包裝在一個帶有mutex
的struct
中以保護對bitset
的訪問,要么使用類似於 atomic shared_ptr
的東西,它允許用新的 bitset 原子地交換舊的bitset
並延遲銷毀舊的,直到所有引用都消失了。
雖然我認為不能保證,但std::bitset
也可以很容易地復制。 您可以使用std::is_trivially_copyable_v
上的static_assert
進行檢查,如果為true
,您還可以使用std::atomic
或std::atomic_ref
這將允許以原子方式訪問位集(即沒有數據競爭)並且可能會使用鎖僅當底層架構不支持對相應大小的 object 的原子訪問時。
還要注意std::bitset b = m[1];
並且m[1]
也會導致未定義的行為,因為std::map
的operator[]
也是修改操作,並且未指定為沒有數據競爭,即使它沒有將新元素插入 map . 您需要使用例如find()
成員 function 來代替。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.