I was first introduced to threads back in the early OS/2 days. From there, I've used OS-level threads and libraries in OS/2, Windows, and Linux. But I must admit, the new C++ standard has me excited. The fact that C++0x (aka C++11) is standardizing threading from a language point of view is a great thing for C++ developers. There are many books, blogs, and web sites discussing both general and specific threading topics, so I wont comment on those aspects. Instead, this article will focus on using std::thread for the first time.
As C++0x/C++11 is increasingly adopted and supported by various compilers, I'm certain some details will change. This article is based on what was generally available in June/July 2011 on Ubuntu 11.04:
There are 2 tricks to using std::thread. The first tells gcc/g++ to enable the new C++0x features, the second is specific to std::thread and tells g++ to use pthread. It seems that std::thread is built on top of -- or relies upon? -- parts of the pthread library. Here is an example showing the exact flags required to compile an application which uses std::thread:
There is also a -std=gnu++0x parm to g++ which apparently defines some GNU extensions to C++0x, but I haven't yet come across a document explaining the details of those extensions.
Under the covers, GCC's implementation of std::thread is definitely still using pthread. This can be confirmed by setting a breakpoint in the thread, and examining the call stack:
The default empty constructor for std::thread doesn't actually create a new thread. For example, this code will still have only the main thread:
Only when a thread is told what code to run is a thread actually created:
Using Valgrind, we can see that every thread we fail to join() or detach() leaks 288 bytes of memory:
To prevent this leak, make sure all threads are properly joined or detached.
exiting the main thread, exiting threads, calling things like exit() from threads
Static variables are allocated from the heap, and thus are shared across all threads. Making a variable static does not prevent concurency problems. For example, with the following example code, the variable foo does not restart at the value zero for each thread that calls the function:
Instead, see the new thread_local keyword to define thread local storage:
differences between std::thread and boost::thread