15 Multithreading ¶
Multithreading is a programming paradigm. In a multithreaded program,
multiple threads execute concurrently (or quasi concurrently) at different
places in the program.
There are three motivations for using multithreading in a program:
- Exploiting CPU hardware with multiple execution units. Nowadays, many CPUs
have 2 to 8 execution cores in a single chip. Additionally, often multiple
CPU chips are combined in a single package. Thus, some CPU packages support
64 or 96 simultaneous threads of execution.
- Simplifying program architecture. When a program has to read from different
file descriptors, network sockets, or event channels at the same time, the
classical single-threaded architecture is to have a main loop which uses
select
or poll
on all the descriptors and then dispatches
according to from which descriptor input arrived. In a multi-threaded
program, you allocate one thread for each descriptor, and these threads can
be programmed and managed independently.
- Offloading work from signal handlers. A signal handler is not allowed to
call
malloc
; therefore you are very limited in what you can do in
a signal handler. But a signal handler can notify a thread, and the thread
can then do the appropriate processing, as complex as it needs to be.
A multithreading API offers
- Primitives for creating threads, for waiting until threads are terminated,
and for reaping their results.
- Primitives through which different threads can operate on the same data or
use some data structures for communicating between the threads. These are
called “mutexes” or “locks”.
- Primitives for executing a certain (initialization) code at most once.
- Primitives for notifying one or more other threads. These are called wait
queues or “condition variables”.
- Primitives for allowing different threads to have different values for a
variable. Such a variable is said to reside in “thread-local storage” or
“thread-specific storage”.
- Primitives for relinquishing control for some time and letting other threads
go.
Note: Programs that achieve multithreading through OpenMP (cf. the gnulib
module ‘openmp’) don’t create and manage their threads themselves.
Nevertheless, they need to use mutexes/locks in many cases.