I am working on a program that needs std::map
and specifically one like this map<string,map<string,int>>
- it is meant to be something like bank change rates - the first string is the original currency and the one in the second map is the desired one and the int is their rate. This whole map will be read only. Do I still need mutexes ? I am a bit confused about the whole thread safety, since this is my first bigger multi-threaded program.
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Difference between Thread#run and Thread#wakeup?
- Selecting only the first few characters in a strin
- Java/Spring MVC: provide request context to child
- What exactly do pointers store? (C++)
If your are completely sure that both the maps are ALWAYS READONLY, Then you never need mutexes.
But you have to be extra careful that no one can update the map by any means during the program execution. Make sure that you are initializing the map at the init stage of program and then never update it for any reason.
If you are confused that, In future you may need to update it in between the program execution, then its better to have macros around the map, which are empty right now. And in future, if you need mutexes around them, just change the macro definition.
PS:: I have used map in answer which can be easily replaced by shared resources. It was for the ease of understanding
If you are talking about the standard
std::map
† and no thread writes to it, no synchronization is required. Concurrent reads without writes are fine.If however at least one thread performs writes on the map, you will indeed need some sort of protection like a mutex.
Be aware that
std::map::operator[]
counts as write, so usestd::map::at
(orstd::map::find
if the key may not exist in the map) instead. You can make the compiler protect you from accidental writes by only referring to the shared map viaconst map&
.†Was clarified to be the case in the OP. For completeness' sake: Note that other classes may have
mutable
members. For those, even access throughconst&
may introduce a race. If in doubt, check the documentation or use something else for parallel programming.The rule of thumb is if you have shared data and at least one thread will be a writer then you need synchronization. If one of the threads is a writer you must have synchronization as you do not want a reader to read an element that is being written to. This can cause issues as the reader might read part of the old value and part of the new value.
In your case since all the threads will only ever being reading data there is nothing they can do that will affect the map so you can have concurrent(unsynchronized) reads.
Wrap a
std::map<std::string, std::map<std::string,int>> const
in a custom class which has onlyconst
member functions [*].This will make sure that all threads which use an object of the class after its creation will only read from it, which is guaranteed to be safe since C++11.
As documentation says:
Wrapping containers in your own custom types is good practice anyway. Increased thread safety is just one positive side effect of that good practice. Other positive effects include increased readability of client code, reduction/adaption of container interface to required functionality, ease of adding additional constraints and checks.
Here is a brief example:
In any case, the thread-safety problem is then reduced to how to make sure that the constructor does not read from an object to which another thread writes. This is often achieved trivially; for example, the object may be constructed before multi-threading even begins, or it may be initialised with hard-coded initialisation lists. In many other cases, the code which creates the object will generally access only other thread-safe functions and local objects.
The point is that concurrent accesses to your object will always be safe once it has been created.
[*] Of course, the
const
member functions should keep their promise and not attempt "workarounds" withmutable
orconst_cast
.