Multi-threading vs. multi-processing

This tutorial focusses on multi-threading rather than multi-processing, though most of the concepts discussed are common to all concurrency. Let's compare these two forms of concurrency. If you're not interested, feel free to skip to the next section.

Multi-threading refers to an application with multiple threads running within a process, while multi-processing refers to an application organised across multiple OS-level processes.

A thread is a stream of instructions within a process. Each thread has its own instruction pointer, set of registers and stack memory. The virtual address space is process specific, or common to all threads within a process. So, data on the heap can be readily accessed by all threads, for good or ill.

Multi-threading is a more "light weight" form of concurrency: there is less context per thread than per process. As a result thread lifetime, context switching and synchronisation costs are lower. The shared address space (noted above) means data sharing requires no extra work.

Multi-processing has the opposite benefits. Since processes are insulated from each other by the OS, an error in one process cannot bring down another process. Contrast this with multi-threading, in which an error in one thread can bring down all the threads in the process. Further, individual processes may run as different users and have different permissions.

Subsequent sections introduce some common problems with multi-threaded code, and solves them using low-level synchronisation constructs.

Further reading

Schmidt, D., Huston, S. (2001). C++ Network Programming. Volume 1. (Chapter 5). Addison-Wesley.