Intro to concurrency in C++
Starting threads
The C++11 standard gave us threads in the C++ standard library. Starting a new thread is pretty straight-forward by constructing a thread
object, giving the entry function as an argument. Execution will start immediately.
#include <thread>
void do_some_work();
int main() {
std::thread my_thread(do_some_work);
}
The thread
constructor also works with any callable type:
class A {
public:
void operator() () const {
...
}
}
int main() {
A foo = A();
std::thread my_thread(foo);
}
It can also take a lambda:
std::thread my_thread([] {
do_something();
do_something_else();
})
Waiting and detaching
Note that while our thread is running, main
is also executing. After main
ends, any running threads are forcefully terminated, so it would be a good idea for them to finish before ending execution in main
.
Waiting on a thread is done by calling join
on the thread
object:
#include <thread>
void do_some_work();
int main() {
std::thread my_thread(do_some_work);
...
my_thread.join();
}
A better approach to joining threads is to use RAII. We make sure our thread
object is automatically joined once it goes out of scope.
class thread_gurad {
std::thread& t
public:
~thread_guard() {
if (t.joinable()) { t.join(); }
}
// Make sure to delete copy and copy-assignment constructors
}
Detaching threads is done by calling detach
on the thread
object. They are also called daemons and will run even after main
ends execution.
References
- Williams, Anthony. C++ Concurrency in Action: Practical Multithreading. Shelter Island, NY: Manning, 2012.