C++ Thread Safety Summary
I would like a summary of what exactly is thread safe in C++ both according to the current standard and C++0x as well as in practice (generally speaking, but also in my case with gcc 4.5.1).
For STL containers, my understanding is that thread safety is not guaranteed according to the current standard. Is it true though that in practice they are thread safe for single writer, multiple reader usage (on gcc and probably most modern compilers)? Is this guaranteed by C++11?.
What about POD types? I know that the standard guarantees nothing, but I've been told that in practice, all are thread safe for reading and writing. Of course even something simple like the i开发者_高级运维ncrement operator may still need synchronization since there could be multiple reads and writes.
I'm primarily interested in the answers, but the why behind the answers would be appreciated to.
None of the things you have mentioned are thread safe, either by the standard or in practice.
The reason that the standards do not mandate thread safety is that thread safety comes with an inherent cost. In general, C++ tries not to give you things that you don't ask for. If you want thread safety, then you have to build it yourself. This is true even in C++ 0x, which includes various synchronization primitives.
The reasons that these things are not thread safe in practice are varied. Generally, the STL containers are not thread safe because each of their basic update operations take multiple steps to accomplish. If a thread tries to read or update a container while another thread is in the process of updating it, the container will be in an indeterminate state, and thus the results will be unpredictable.
In the case of POD types, reads and writes can also take multiple steps to complete. This simplest example is a 64-bit integer on a 32-bit machine. It takes at least two instructions to either read or set the value. Once again, this means that if a thread tries to read or update the value while another thread is in the process of updating it, the results will be unpredictable.
The current standard doesn't mention threading at all, in any respect. In practice, the standard containers provide thread-safe reading, but require synchronization for writing.
C++ 0x doesn't talk much (at all?) specifically about containers with respect to thread safety/sharing, but does talk about assignments and such. In the end, it comes out pretty much the same though -- even though the object is in a container, you're reading/writing data, and you have to synchronize when/if at least one thread may modify the data.
POD data doesn't really change much: modifications will require synchronization as a general rule. There's usually some subset of data types for which operations are normally atomic, but the members of that subset vary by platform. It'll typically include types up to the native word size of the hardware allocated with "natural" alignment; anything else is open to a lot more question.
POD and Standard defined types do not have any thread safety. It is entirely up to the code user to synchronize their threads to ensure that nothing bad happens.
In C++0x, I have little idea; not really checking up on that area of the Standard.
Neither C nor C++ have concurrency primitives built into the language in the way (say) java has with synchronised
. This is (I believe) deliberate - even on modern versions - to avoid having the overhead when it is not needed. Unix did not support lightweight processes in the early days, so threading was largely a kernel issue.
Various proprietary thread libraries (e.g. Solaris threads) were produced by vendors, and the industry ultimately standardised on the pthread
library, initially with a purely userspace threading model (blocking calls like I/O would block all threads) and later with kernel thread support. Windows, OS/2 and various other operating systems offered proprietary thread facilities.
C/C++ are designed to run on systems that may or may not have thread support, and to run efficiently - so thread support is an optional extra. One of the design philosophies of C++ is that the programmer should not have to pay for features they don't use. One could argue the merits of this approach in an era of multi core machines but assuming 'the entire world is a PC' has been considered a major pitfall in writing portable C code for some decades now.
The net effect is that threading tends to be platform specific, although cross-platform threading libraries do exist.
精彩评论