Multithreading runs multiple paths of execution within one program. Threads may execute concurrently through context switching or in parallel on multiple CPU cores, while sharing code, data, and external resources. section 16.0 section 16.1
Designing a multithreaded program requires coordinating execution and protecting shared resources:
- Identify critical regions: statements that access shared data, files, printers, or other resources. section 16.2
- Guard critical regions with a mutex, allowing one thread to lock the resource while others block. section 16.2
- Use semaphores when multiple readers may access a resource simultaneously while writers require exclusion, and condition objects for finer producer–consumer synchronization. section 16.0
- Account for race conditions, deadlocks, scheduling variability, context-switching costs, and synchronization overhead. section 16.5
Protecting a shared print stream
Three threads print different messages one character at a time. Without synchronization, their output becomes intermixed and can differ on every run. A shared Lock fixes the design: each thread acquires the mutex before printing its complete message and releases it afterward. Using `with printing_mutex` expresses the same guarded region more safely; adding `sleep` outside the lock allows the threads to interleave between messages. section 16.2.1
Figure 16.1 A multithreaded application with three threads. The threads share the application’s internal resources of code and data in memory and external resources such as printers and files. The runtime system gives each thread its own runtime stack and the appearance of having its own set of machine registers.
Use the figure to see how threads share application code, data, printers, and files while retaining separate runtime stacks. section 16.1










