CMU Computer Systems: Synchronization (Advanced)
Producer-Consumer Problem
- Common synchronization pattern
- Producer waits for empty slot, inserts item in buffer, and notifies consumer
- Consumer waits for item, removes it from buffer, and notifies producer
- Examples
- Multimedia processing
- Producer creates MPEG video frames, consumer renders them
- Event-driven graphical use interfaces
- Producer detects mouse clicks, mouse movements, and keyboard clicks and inserts corresponding events in buffer
- Consumer retrieves events from buffer and paints the display
Readers-Writers Problem
- Generalization of the mutual exclusion problem
- Problem statement
- Reader threads only read the object
- Writer threads modify the object
- Writers must have exclusive access to the object
- Unlimited number of readers can access the object
- Occurs frequently in real systems, e.g.,
- Online airline reservation system
- Multithreaded caching Web proxy
Variants of Readers-Writers
- First readers-writers problem (favors readers)
- No reader should be kept waiting unless a writer has already been granted permission to use the object
- A reader that arrives after a waiting writer gets priority over the wrier
- Second readers-writers problem (favors writers)
- Once a writer is ready to write, it performs its write as soon as possible
- A reader that arrives after a writer must wait, even if the writer is also waiting
- Starvation is possible in both cases
Crucial concept: Thread Safety
- Functions called from a thread must be thread-safe
- A function is thread-safe if it will always produce correct results when called repeatedly from multiple concurrent threads
- Classes of thread-unsafe functions
- Functions that do not protect shared variables
- Failing to protect shared variables
- Functions that keep state across multiple invocations
- Relying on persistent state across multiple function invocations
- Functions that return a pointer to a static variable
- Fix 1. Rewrite function so caller passes address of variable to store result
- Fix 2. Lock-and-copy
- Functions that call thread-unsafe functions
- Calling one thread-unsafe function makes the entire function that calls it thread-unsafe
Reentrant Functions
- A function is reentrant if it accesses no shared variables when called by multiple threads
- Important subset of thread-safe functions
- Require no synchronization functions
- Only way to make a Class 2 function thread-safe is to make it reentrant
Worries
- Races
- A race occurs when correctness of the program depends on one thread reaching point x before another thread reaches point y
- Deadlock
- A process is deadlock if it is waiting for a condition that will never be true