50

I have trouble finding any up-to-date information on this.

Do C++11 versions of STL containers have some level of thread safety guaranteed?

I do expect that they don't, due to performance reasons. But then again, that's why we have both std::vector::operator[] and std::vector::at.

Azeem
  • 11,148
  • 4
  • 27
  • 40
Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
  • 2
    My guess is, that bounds checking is on a totally different performance scale than mutexes or the like. Could be wrong though. – Constantinius Oct 17 '12 at 10:03
  • 8
    Thread safety at the level of container access is often useless as you want to write things like "cash[i] = cash[i] + total" and the locking needs to be at a higher level than on the container itsself. – jcoder Oct 17 '12 at 10:07
  • 2
    A related question [Safe parallel read-only access to a STL container](http://stackoverflow.com/questions/10833512/safe-parallel-read-only-access-to-a-stl-container?rq=1) – Bo Persson Oct 17 '12 at 10:52
  • 4
    There are quite a few guarantees (sections [res.on.data.races], [container.requirements.dataraces] and of course the prerequisite [intro.multithread]). @Mr.C64's answer is very much to the point, if you want a more specific answer (possibly with standard quotes), please adjust the question. – avakar Oct 17 '12 at 11:06
  • @avakar It would be great if you could make an answer for quotes. I have the standard, but It would be nice to close the question an exhaustive answer. – Šimon Tóth Oct 17 '12 at 11:15

3 Answers3

47

Since the existing answers don't cover it (only a comment does), I'll just mention 23.2.2 [container.requirements.dataraces] of the current C++ standard specification which says:

implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting vector<bool>, are modified concurrently.

i.e. it's safe to access distinct elements of the same container, so for example you can have a global std::vector<std::future<int>> of ten elements and have ten threads which each write to a different element of the vector.

Apart from that, the same rules apply to containers as for the rest of the standard library (see 17.6.5.9 [res.on.data.races]), as Mr.C64's answer says, and additionally [container.requirements.dataraces] lists some non-const member functions of containers that can be called safely because they only return non-const references to elements, they don't actually modify anything (in general any non-const member function must be considered a modification.)

Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
31

I think STL containers offer the following basic thread-safety guarantee:

  • simultaneous reads of the same object are OK

  • simultaneous read/writes of different objects are OK

But you have to use some form of custom synchronization (e.g. critical section) if you want to do something different, like e.g. simultaneous writes on the same object.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • 11
    What is the meaning of "object" in this context? Element or container? – Šimon Tóth Oct 17 '12 at 10:28
  • For example, is it OK to execute `myvec[0] = 0` and `myvec[1]` "simultaneously" in different threads? If the "object" is the container then that's a read and a write to the same object, but if the "object" is the element then it isn't. You can also imagine a container like a splay tree in which simultaneous reads to the container are not OK, but presumably if there's a guarantee that simultaneous reads are OK then it is forbidden for `std::map` to be implemented as a splay tree that's unsafe in that respect. – Steve Jessop Oct 17 '12 at 10:33
  • @Let_Me_Be: "object" == container in this case. – Mr.C64 Oct 17 '12 at 11:06
  • 5
    @SteveJessop, `myvec[0] = 0` while simultaneously `myvec[1]` is OK -- `operator[]` on sequential containers must avoid races ([container.requirements.dataraces]/1). This is not true for unordered and associative containers. – avakar Oct 17 '12 at 11:08
  • @avakar, I believe that requirement applies to all standard containers, not just the sequence containers. I'll request a new issue to clarify the wording. – Jonathan Wakely Oct 17 '12 at 17:47
  • 2
    @JonathanWakely, I'm basing this on n3337/23.2.2/1: "For purposes of avoiding data races (17.6.5.9), implementations shall consider the following functions to be const: begin, end, [...] and, except in associative or unordered associative containers, operator[]." – avakar Oct 17 '12 at 17:51
  • @JonathanWakely, if you already have a valid pointer/reference to the elements, you can read them simultaneously. The data race could occur in the invocation of `[]` on the same container. – avakar Oct 17 '12 at 17:53
  • @avakar, Ah, sorry, I thought you meant §2 where it says "sequence", I think _that_ requirement applies to all containers. If you already have a valid reference to the elements you can **write** to them simultaneously iff they're different elements. – Jonathan Wakely Oct 17 '12 at 17:53
-6

No. Check out PPL or Intel TBB for thread safe STL-like containers.

Like others have noted they have usual "multiple reader thread safety" but that is even pre C++11. Ofc this doesnt mean single writer multiple readers. It means 0 writers. :)

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 1
    "but that is even pre C++11" No it isn't. C++03 doesn't even know what threading *is*. So it does not specify behavior dealing with threading. – Nicol Bolas Oct 18 '12 at 01:30
  • He didn't ask how compilers implement the standard. He what *guarantees* the *standard* provided; "guarantees" that implementations provide are therefore *irrelevant*. – Nicol Bolas Oct 18 '12 at 09:51
  • that is your opinion, OP doesnt specifies that he is interested in just the standard and not reality. But it is pointless discussion since first 2 chars of my answer are the most important part. Rest of the importance mostly lies in second sentence. :) – NoSenseEtAl Oct 18 '12 at 10:33
  • 7
    @NoSenseEtAl And in fact those *"first 2 chars"* that *"are the most important part"* are wrong, since the other answers have clearly shown that the there is indeed some level of thread-safety guaranteed, be it only for simultaneous reads without any writes, or certain functions. So a definite *"No"* is just too general to be correct in any way. – Christian Rau Oct 18 '12 at 11:35
  • I dont consider that multiple readers is noteworthy(though I added that long time before ppl complained in the comments so that ppl dont get confused). Then again maybe Im not like average dev( In a sense that I see read safety as trivial - see my first comment) – NoSenseEtAl Oct 18 '12 at 11:56
  • 4
    @NoSenseEtAl: "*I dont consider that multiple readers is noteworthy*" But he didn't ask what *you* considered noteworthy. He asked for facts: "Do C++11 versions of STL containers have some level of thread safety guaranteed?" The factual answer is "Yes," because the standard does have *some level* of guarantees. – Nicol Bolas Oct 18 '12 at 17:23
  • Seeing the downvotes, I am reminded of what I read somewhere about Courts' passing judgements: `We can't interpret what was on the minds of legislators. We only go by the letter of the law`. Seems to be a question of what was in the OP's mind when he asked about `some level of thread safety` – Arundale Ramanathan Mar 02 '23 at 04:58