Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Part Two.  Surviving the Real World


Chapter 10. Threading

The subject of multithreading is a pretty big one, and worthy of several books all to itself [Bute1997, Rich1997]. In an attempt to simplify, I intend to stipulate that the challenges of multithreaded programming all pertain to synchronization of access to resources. The resources may be a single variable, a class, or they may even be some product of one thread that is to be consumed by another. The point is that if two or more threads need to access the same resource their access needs to be made safe. Alas, both C and C++ were developed before multithreading became as popular as it now is. Hence:

Imperfection: C and C++ say nothing about threading.


What does that mean? Well, in no part of the standard will you find any reference to threading.[1] Does this mean that you cannot write multithreaded programs with C++? Certainly not. But it does mean that C++ provides no support for multithreaded programming. The practical consequences of this are considerable.

[1] The only occurrence of the word thread is (C++-98: 15.1;2) when discussing threads of control in exception-handling.

The two classic concepts [Bute1997, Rich1997] one must be wary of when writing multitasking systems are race-conditions and deadlocks. Race-conditions occur when two separate threads of execution have access to the same resource at the same time. Note that I'm using the term "thread of execution" here to include processes on the same system and threads in the same process or in different processes in the same host system.

To protect against race-conditions, multitasking systems use synchronization mechanisms, such as mutexes, condition variables, and semaphores [Bute1997, Rich1997], to prevent concurrent access to shared resources. When one thread of execution has acquired a resource (also called locking the resource), other threads are locked out, and go into a wait state until the resource is released (unlocked).

Naturally the interaction of two or more independent threads of execution is potentially highly complex, and it is possible to have two threads each holding a resource and waiting for the other to release. This is known as a deadlock. Less common, but just as deadly, is livelock, whereby two or more processes are constantly changing state in response to changes in the others and so no progress can be made.

Both race conditions and deadlocks are hard to predict, or test for, which is one of the practical challenges of multithreaded programming. Even though deadlocks are very easy to detect—your executable stops—they are still hard to diagnose, since your process (or a thread within it) has hung.


      Previous section   Next section