最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Is std::atomic<std::map<S, T>> thread-safe for reading and writing? - Stack Overflow

programmeradmin1浏览0评论

Suppose I have a std::atomic<std::map<std::string, std::string>> and different threads do operations like std::string foo = map["bar"]; and map["bar"] = "baz". I don't save references or pointers to the values in the map. I just need storing and retrieving values to happen thread-safely. Does this work, or do I need to use a lock or such?

Suppose I have a std::atomic<std::map<std::string, std::string>> and different threads do operations like std::string foo = map["bar"]; and map["bar"] = "baz". I don't save references or pointers to the values in the map. I just need storing and retrieving values to happen thread-safely. Does this work, or do I need to use a lock or such?

Share Improve this question asked Mar 12 at 9:54 H.v.M.H.v.M. 1,7093 gold badges20 silver badges45 bronze badges 3
  • 5 Please post an actual code example. If map is an std::atomic then map["bar"] will simply not compile – 463035818_is_not_an_ai Commented Mar 12 at 9:59
  • 1 Use of atomic make seance only for small trivial types. std::atomic<std::map<std::string, std::string>> will not give you hardware support and whole advantage of it is lost. If you do not know this this means you should not use this. This is not accident that talk about using std::atomic has "juggling with razors" in it. So I would recommend master other multi threading primitives before using std::atomic. – Marek R Commented Mar 12 at 10:11
  • "Suppose I have a std::atomic<std::map<std::string, std::string>>" You don't. Not in the C++ language. That won't compile. – Drew Dormann Commented Mar 13 at 19:26
Add a comment  | 

2 Answers 2

Reset to default 6

Suppose I have a std::atomic<std::map<std::string, std::string>>

Then your program is ill-formed. Except for specialisations defined by the standard, std::atomic<T> requires that T be TriviallyCopyable, CopyConstructible and CopyAssignable. No specialisation of std::map satisfies TriviallyCopyable.

Even if you were allowed to form a std::atomic<std::map<std::string, std::string>> map;, you wouldn't be able to do std::string foo = map["bar"]; nor map["bar"] = "baz".

The former would need to be something like std::string foo = map.load()["bar"];, and the latter auto local = map.load(); local["bar"] = "baz"; map.store(local); to be well formed, let alone express atomic semantics. The load is thread safe (ignoring that you lose the insertion of a default string if "bar" is absent), but the store is not, as something else can modify the map between the two accesses.

There is no std::atomic<std::map<S, T>>, hence it cannot be thread-safe to read or write from it. But let's go a step back and consider what std::atomic gives us.

Generally std::atomic<T> allows to load and store the value as a whole in a thread-safe way. Load and store are each atomic. No other thread can interfere with a load nor a store.

However, calling operator[] on a std::map is not just a store nor a load. Ergo atomic access to the map as a whole is not sufficient.

Here

std::map<std::string,std::string> x;
std::string foo = x["bar"];

the second line looks up the value in the map for the given key, if no value exists it inserts one, then it returns a reference to the mapped value. std::atomic::load returns a copy, hence a wrong (!) implementation of the semantics of operator[] in terms of load and store would be

auto m = map.load();           
std::string foo = m["bar"];
map.store(foo);

While the load and the store individually are atomic and thread-safe, the operation as a whole is not. std::atomic simply does not help here.

Last but not least, std::atomic<T> requires T to be TriviallyCopyable, but a std::map is not TriviallyCopyable.

发布评论

评论列表(0)

  1. 暂无评论