Classical Synchronization Problems • Readers-Writers ProblemMedium⏱️ ~3 min
The Semaphore Solution and Lightswitch Pattern
Key Insight
The lightswitch pattern: first reader locks out writers (turns on the light), last reader unlocks (turns off the light). Writers simply wait for the room to be empty.
Lightswitch Pattern
How The Lightswitch Works
Imagine a room with a light switch. First person entering turns on the light (locks out writers). Last person leaving turns off the light (allows writers). The readers counter tracks how many are in the room.
Why mutex Protects readers
Multiple readers might try to increment/decrement the counter simultaneously. The mutex ensures the counter updates and the conditional signal/wait are atomic.
Writer Simplicity
Writers just wait on roomEmpty. They do not care how many readers there are. Either the room is empty (proceed) or not (wait).
Problem: This solution can starve writers. If readers keep arriving, a writer waits forever.
💡 Key Takeaways
✓Three variables: readers counter (int, starts 0), mutex semaphore (protects counter), roomEmpty semaphore (1 if no threads in critical section, 0 otherwise)
✓Writers simply wait on roomEmpty, execute, signal roomEmpty; readers coordinate via counter where first waits on roomEmpty (blocking writers) and last signals roomEmpty
✓Only one reader queues on roomEmpty at a time (while holding mutex); subsequent readers queue on mutex; multiple writers can queue on roomEmpty
✓Lightswitch pattern encapsulates first-in-locks, last-out-unlocks: lock() waits on semaphore only if counter was 0, unlock() signals only if counter becomes 0
✓Reader entry: mutex.wait(), readers++, if readers==1 then roomEmpty.wait(), mutex.signal(); exit: mutex.wait(), readers--, if readers==0 then roomEmpty.signal(), mutex.signal()
📌 Examples
1Lightswitch analogy: 5 people enter dark room sequentially; first person turns on light (locks), persons 2-5 enter without touching switch, persons 1-4 leave without touching switch, person 5 (last out) turns off light (unlocks)
2Reader queuing: writer W holds roomEmpty; reader R1 arrives, blocks on roomEmpty while holding mutex; readers R2, R3 arrive and block on mutex (not roomEmpty); W exits, R1 proceeds, then R2 and R3 proceed immediately
3Counter race condition without mutex: two readers arrive simultaneously, both read readers=0, both increment to 1, both call roomEmpty.wait(); second wait blocks forever because roomEmpty is already 0 from first wait