%threads.entities; ]>
Overview
Introduction &Boost.Threads; allows C++ programs to execute as multiple, asynchronous, independent threads-of-execution. Each thread has its own machine state including program instruction counter and registers. Programs which execute as multiple threads are called multithreaded programs to distinguish them from traditional single-threaded programs. The glossary gives a more complete description of the multithreading execution environment. Multithreading provides several advantages: Programs which would otherwise block waiting for some external event can continue to respond if the blocking operation is placed in a separate thread. Multithreading is usually an absolute requirement for these programs. Well-designed multithreaded programs may execute faster than single-threaded programs, particularly on multiprocessor hardware. Note, however, that poorly-designed multithreaded programs are often slower than single-threaded programs. Some program designs may be easier to formulate using a multithreaded approach. After all, the real world is asynchronous!
Dangers
General considerations Beyond the errors which can occur in single-threaded programs, multithreaded programs are subject to additional errors: Race conditions Deadlock (sometimes called "deadly embrace") Priority failures (priority inversion, infinite overtaking, starvation, etc.) Every multithreaded program must be designed carefully to avoid these errors. These aren't rare or exotic failures - they are virtually guaranteed to occur unless multithreaded code is designed to avoid them. Priority failures are somewhat less common, but are nonetheless serious. The &Boost.Threads; design attempts to minimize these errors, but they will still occur unless the programmer proactively designs to avoid them. Please also see for additional, implementation-specific considerations.
Testing and debugging considerations Multithreaded programs are non-deterministic. In other words, the same program with the same input data may follow different execution paths each time it is invoked. That can make testing and debugging a nightmare: Failures are often not repeatable. Probe effect causes debuggers to produce very different results from non-debug uses. Debuggers require special support to show thread state. Tests on a single processor system may give no indication of serious errors which would appear on multiprocessor systems, and visa versa. Thus test cases should include a varying number of processors. For programs which create a varying number of threads according to workload, tests which don't span the full range of possibilities may miss serious errors.
Getting a head start Although it might appear that multithreaded programs are inherently unreliable, many reliable multithreaded programs do exist. Multithreading techniques are known which lead to reliable programs. Design patterns for reliable multithreaded programs, including the important monitor pattern, are presented in Pattern-Oriented Software Architecture Volume 2 - Patterns for Concurrent and Networked Objects &cite.SchmidtStalRohnertBuschmann;. Many important multithreading programming considerations (independent of threading library) are discussed in Programming with POSIX Threads &cite.Butenhof97;. Doing some reading before attempting multithreaded designs will give you a head start toward reliable multithreaded programs.
C++ Standard Library usage in multithreaded programs
Runtime libraries Warning: Multithreaded programs such as those using &Boost.Threads; must link to thread-safe versions of all runtime libraries used by the program, including the runtime library for the C++ Standard Library. Failure to do so will cause race conditions to occur when multiple threads simultaneously execute runtime library functions for new, delete, or other language features which imply shared state.
Potentially non-thread-safe functions Certain C++ Standard Library functions inherited from C are particular problems because they hold internal state between calls: rand strtok asctime ctime gmtime localtime It is possible to write thread-safe implementations of these by using thread specific storage (see boost::thread_specific_ptr), and several C++ compiler vendors do just that. The technique is well-know and is explained in &cite.Butenhof97;. But at least one vendor (HP-UX) does not provide thread-safe implementations of the above functions in their otherwise thread-safe runtime library. Instead they provide replacement functions with different names and arguments. Recommendation: For the most portable, yet thread-safe code, use Boost replacements for the problem functions. See the Boost Random Number Library and Boost Tokenizer Library.
Common guarantees for all &Boost.Threads; components
Exceptions &Boost.Threads; destructors never throw exceptions. Unless otherwise specified, other &Boost.Threads; functions that do not have an exception-specification may throw implementation-defined exceptions. In particular, &Boost.Threads; reports failure to allocate storage by throwing an exception of type std::bad_alloc or a class derived from std::bad_alloc, failure to obtain thread resources other than memory by throwing an exception of type boost::thread_resource_error, and certain lock related failures by throwing an exception of type boost::lock_error. Rationale: Follows the C++ Standard Library practice of allowing all functions except destructors or other specified functions to throw exceptions on errors.
NonCopyable requirement &Boost.Threads; classes documented as meeting the NonCopyable requirement disallow copy construction and copy assignment. For the sake of exposition, the synopsis of such classes show private derivation from boost::noncopyable. Users should not depend on this derivation, however, as implementations are free to meet the NonCopyable requirement in other ways.