C++11 concurrency: threads

C++11 provides richer support for concurrency than the previous standard. Among the new features is the std::thread class (from the <thread> header) that represents a single thread of execution. Unlike other APIs for creating threads, such as CreateThread, std::thread can work with (regular) functions, lambdas or functors (i.e. classes implementing operator()) and allows you to pass any number of parameters to the thread function.

Let’s see a simple example.

In this example t is a thread object representing the thread under which function func() runs. The call to join blocks the calling thread (in this case the main thread) until the joined thread finishes execution.

If the thread function returns a value, it is ignored. However, the function can take any number of parameters.

The output is:

It is important to note that the parameters to the thread function are passed by value. If you need to pass references you need to use std::ref or std::cref.
The following program prints 42.

But if we change to t(func, std::ref(a)) it prints 43.

In the next example we execute a lambda on a second thread. The lambda doesn’t do much, except for printing some message and sleeping for a while.

The output looks like this (obviously the id of the threads differ for each run).

But if we start two threads, the the output looks different:

The reason is the function running on a separate thread is using std::cout, which is an object representing a stream. This is a shared object of a class that is not thread-safe, therefore the access from different threads to it must be synchronized. There are different mechanisms provided by C++11 to do that (will discuss them in a later post), but one of them is std::mutex (notice there are four flavors of mutexes).

The correct, synchronized code should look like this:

In this examples I have used several functions from the std::this_thread namespace (also defined in the <thread> header). The helper functions from this namespace are:

  • get_id: returns the id of the current thread
  • yield: tells the scheduler to run other threads and can be used when you are in a busy waiting state
  • sleep_for: blocks the execution of the current thread for at least the specified period
  • sleep_util: blocks the execution of the current thread until the specified moment of time has been reached

Apart from join() the thread class provides two more operations:

  • swap: exchanges the underlying handles of two thread objects
  • detach: allows a thread of execution to continue independently of the thread object. Detached threads are no longer joinable (you cannot wait for them).

What happens though if a function running on a separate thread throws an exception? You cannot actually catch that exception in the thread that’s waiting for the faulty thread, because std::terminate is called and this aborts the program.

If func() throws an exception, the following catch block won’t be reached.

What can be done then? To propagate exceptions between threads you could catch them in thread function and store them in a place where they can be lately looked-up. Possible solutions are detailed here and here.

In future posts we will look at other concurrency features from C++11 (such as synchronization mechanisms or tasks).

One thought on “C++11 concurrency: threads

  1. Pingback: Introduction to C++11 Concurrency | musingstudio

Leave a Reply