C++11 STL containers and thread safety
Solution 1
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.)
Solution 2
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.
Related videos on Youtube
Šimon Tóth
Backend oriented Software developer and Researcher with industry experience starting in 2004.
Updated on July 09, 2022Comments
-
Šimon Tóth almost 2 years
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[]
andstd::vector::at
.-
Constantinius over 11 yearsMy guess is, that bounds checking is on a totally different performance scale than mutexes or the like. Could be wrong though.
-
jcoder over 11 yearsThread 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.
-
Bo Persson over 11 yearsA related question Safe parallel read-only access to a STL container
-
avakar over 11 yearsThere 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.
-
Šimon Tóth over 11 years@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 over 11 yearsWhat is the meaning of "object" in this context? Element or container?
-
Steve Jessop over 11 yearsFor example, is it OK to execute
myvec[0] = 0
andmyvec[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 forstd::map
to be implemented as a splay tree that's unsafe in that respect. -
Mr.C64 over 11 years@Let_Me_Be: "object" == container in this case.
-
avakar over 11 years@SteveJessop,
myvec[0] = 0
while simultaneouslymyvec[1]
is OK --operator[]
on sequential containers must avoid races ([container.requirements.dataraces]/1). This is not true for unordered and associative containers. -
Jonathan Wakely over 11 years@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.
-
avakar over 11 years@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 over 11 years@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. -
Jonathan Wakely over 11 years@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.
-
Nicol Bolas over 11 years"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 over 11 yearsHe didn't ask how compilers implement the standard. He what guarantees the standard provided; "guarantees" that implementations provide are therefore irrelevant.
-
NoSenseEtAl over 11 yearsthat 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. :)
-
Christian Rau over 11 years@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.
-
NoSenseEtAl over 11 yearsI 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)
-
Nicol Bolas over 11 years@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.