21

I have a std::map that I use to map values (field ID's) to a human readable string. This map is initialised once when my program starts before any other threads are started, and after that it is never modified again. Right now, I give every thread its own copy of this (rather large) map but this is obviously inefficient use of memory and it slows program startup. So I was thinking of giving each thread a pointer to the map, but that raises a thread-safety issue.

If all I'm doing is reading from the map using the following code:

std::string name;
//here N is the field id for which I want the human readable name
unsigned field_id = N; 
std::map<unsigned,std::string>::const_iterator map_it;

// fields_p is a const std::map<unsigned, std::string>* to the map concerned.
// multiple threads will share this.
map_it = fields_p->find(field_id);
if (map_it != fields_p->end())
{
    name = map_it->second;
}
else
{
    name = "";
}

Will this work or are there issues with reading a std::map from multiple threads?

Note: I'm working with visual studio 2008 currently, but I'd like this to work acros most main STL implementations.

Update: Edited code sample for const correctness.

jilles de wit
  • 7,060
  • 3
  • 26
  • 50

4 Answers4

16

This will work from multiple threads as long as your map remains the same. The map you use is immutable de facto so any find will actually do a find in a map which does not change.

Here is a relevant link: http://www.sgi.com/tech/stl/thread_safety.html

The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe. If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.

You fall into he "simultaneous read accesses to shared containers" category.

Note: this is true for the SGI implementation. You need to check if you use another implementation. Of the two implementations which seem widely used as an alternative, STLPort has built-in thread safety as I know. I don't know about the Apache implementation though.

laura
  • 7,280
  • 4
  • 35
  • 43
  • 1
    Note: The answer is limited to the SGI STL implemenation. The OP did not mention which one is used. – foraidt Dec 04 '09 at 10:58
  • I use the implementation that comes with visual studio 2008, but I was looking for an answer that covers the std::map in general, or at least across most implementations if this is at all possible. – jilles de wit Dec 04 '09 at 11:31
  • Check the STL/CRL documentation(for VS20008): http://msdn.microsoft.com/en-us/library/bb385954.aspx. In my opinion, there is no reason why this would be untrue for the VS2008 implementation: it uses balanced binary trees as well as support for maps. I am sure they must have some sort of comment of thread safety in the documentation though – laura Dec 04 '09 at 11:41
  • I'm not convinced. Just because nobody's modifying the map doesn't necessarily make it thread-safe. We don't know the details of the object's internals. There could be things going on under the hood such as caching that we don't know about. (I once wrote a hash table that cached the most recently-returned key-value pair) – Edward Falk Jul 02 '21 at 20:01
9

It should be fine. You can use const references to it if you want to document/enforce read-only behaviour.

Note that correctness isn't guaranteed (in principle the map could choose to rebalance itself on a call to find), even if you do use const methods only (a really perverse implementation could declare the tree mutable). However, this seems pretty unlikely in practise.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • I would consider an implementation with mutable non thread safe internals buggy. – Gunther Piez Dec 04 '09 at 12:28
  • I updated my code slightly to use a const reference to the map and an const_iterator – jilles de wit Dec 04 '09 at 13:43
  • drhirsch, a non-threadsafe implementation could still be standards compliant, but it would certainly be poor-quality. – Useless Dec 04 '09 at 13:48
  • @Useless: Not necessarily. Splay trees update the tree during lookup, which makes it faster to look up recently accessed elements. – Jørgen Fogh Aug 16 '11 at 13:25
  • 1
    Good point, although ideally such a map wouldn't provide const accessors and then make it's tree mutable. Also: way to resurrect an old topic! :-) – Useless Aug 17 '11 at 11:28
  • It seems to me that if the class is documented as not thread-safe (more specifically: *not* documented to be thread-safe), then it's free to implement its internals in a non-thread-safe way. – Edward Falk Jul 02 '21 at 20:06
  • You're absolutely correct in general, which is why I said correctness isn't guaranteed. However, none of the standard library implementations I've looked at have `mutable` implementation details being mutated via const accessors/iterators. There's no reason to use them with a red-black tree. I'm certainly not aware of any `std::map` implemented using a splay tree. – Useless Jul 02 '21 at 22:12
3

Yes it is.

See related post with same question about std::set:

Is the C++ std::set thread-safe?

Community
  • 1
  • 1
RED SOFT ADAIR
  • 12,032
  • 10
  • 54
  • 92
0

For MS STL implementation

Thread Safety in the C++ Standard Library

The following thread safety rules apply to all classes in the C++ Standard Library—this includes shared_ptr, as described below. Stronger guarantees are sometimes provided—for example, the standard iostream objects, as described below, and types specifically intended for multithreading, like those in .

An object is thread-safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously.