C++ 中的 std::map 不同線程操作不同 key 是否需要加鎖?
map中的key為std::string,value為std::atomic_ulong類型。map創建並初始化之後,不會再有任何的insert和delete鍵值對的操作。僅有的操作就是不同的線程會訪問不同的key,對key對應的value做加1和讀取操作,請問這種情況下,是否需要加鎖?
如果沒有人在寫,那你多少個線程怎麼讀都是不用加鎖的。但是只要有一個人寫了,所有的讀都得加鎖。
根據你的描述:
僅有的操作就是不同的線程會訪問不同的key,對key對應的value做加1和讀取操作,……
那為什麼不使用 thread local 的 atomic_ulong?要 map 幹什麼?
進一步,如果使用了 thread local,那還要 atomic 幹什麼,直接用 unsigned long 不就行了?
不需要。但最好是用 find(), 不要用 operator[],因為後者在找不到 key 的時候會做插入。
容器庫 - cppreference.com
能同時在同一容器上由不同線程調用 const 成員函數。而且,成員函數 begin() 、 end(), rbegin() 、 rend() 、 front() 、 back() 、 data() 、 find() 、 lower_bound() 、 upper_bound() 、 equal_range() 、 at() 和除了關聯容器中的 operator[] 對於線程安全的目標表現如同 const (即它們亦能同時在同一容器上由不同線程調用)。更廣泛而言, C++ 標準庫函數不修改對象,除非這些對象能直接或間接地經由函數參數,包含 this 指針訪問。
只讀的話不需要,但是要知道operator[]在找不到的時候是會插入的,所以為了避免隱含的錯誤,請用find
嚴格的講,STL實現只保證在多線程同時(只)使用const成員函數時線程安全,所以還是用find保險一點
推薦書本《Effective STL》,裡面有具體的講解。
如果對 map 只讀,不需要加鎖。
關於 Counting,推薦一本書
Is Parallel Programming Hard, And, If So, What Can You Do About It?
第五章整章都在講 Counting。
這也算是紅黑樹的一個優點了,get操作不調整樹結構,因此可以多線程訪問結點。
如果做了某些優化就不能了,比如get操作降低結點高度。
推薦閱讀:
※g++中數組和vector元素個數最多只能是2^31 -1個嗎?
※子類所繼承的兩個父類有同名純虛函數,怎麼辦?
※為什麼GCC5.x.x版本中的std::string不再採用寫時複製的實現,而改用了SSO的實現?
※如何用 C/C++ 求 1 到 1000 內的所有完全數?
※reinterpret_cast把const string*轉換成const char*出錯?
TAG:C |