Threading

Condition Variables

std::condition_variable, from #include <condition_variable>  is a synchronization object used for inter-thread notification. Note that two additional shared variables need to be used alongside a condition variable to achieve thread-to-thread notification, a mutex and a boolean (a.k.a a condition flag).

Run this code at http://cpp.sh/7es7i.

The program above should print:

On entry, the  wait()  method simultaneously unlocks the mutex and waits for the condition. On exit, the  wait()  method relocks the mutex.

Note the use of the boolean variable called wakeup_. This has to be used to protect against spurious wakeups. This is where the thread that is waiting on a condition variable gets woken up, even though it has not been notified. The code checks the boolean, and if still false, goes back to sleep by calling wait() again.

If you want to do more than just send notifications between threads, and actually send data, have a look at futures and promises instead.

Locks

Locks are C++ objects which provide safety and convenience when locking and unlock mutexes (you could call them mutex wrappers). The two main locks available in C++ are std::unique_lock and std::lock_guard, both from #include <mutex>.

Unique Locks

A std::unique_lock can be instructed to take ownership of a mutex. It will either release the mutex when it is manually unlocked (e.g. via unlock()) or when it goes out of scope and gets destroyed.

When a std::unique_lock is created, you can instruct it to not lock the mutex by deferring:

Lock Guards

A lock_guard  tries to take ownership of a mutex when it is created. When control leaves the scope that lock_guard  was created in, lock_guard  is destroyed and the mutex is released.

Unique Locks vs. Lock Guards

Recommendation: Use a lock_guard unless you need to manually release the mutex without having to rely on a lock_guard going out of scope.

Threads

std::thread has been in the C++ language since C++11. It’s introduction standardized the way threads are used in C++, as before this time platform-specific implementations were the only option (e.g. pthread for POSIX systems).

A Basic Example

The thread begins execution as soon as the object is created (there is no thread.start()).

Common Errors

terminate called without an active exception

This runtime error usually occurs when your program tries to end while there are still threads running.

You will usually see the following terminal output:

You can fix this by making sure you call join() for all threads created by the program.

 

 

Posted: May 9th, 2017 at 4:19 am
Last Updated on: September 12th, 2017 at 11:54 am