liveBook · Manning

Synchronization

As explained in Grokking Concurrency

Synchronization is coordination that controls access to shared resources and orders task execution so required exclusivity or dependencies are respected.

Imagine two people sending files to one printer. If the printer alternates between their files line by line, neither gets the intended result. Synchronization coordinates tasks so one can finish using the printer before another takes its turn. It also makes a task wait when its work depends on another task finishing first. section 8.3 section 2.8

This matters especially for threads: they share an address space, so one thread can read data another has changed. A critical section is code that multiple tasks could execute while accessing a shared resource. Without coordination, the result may depend on which task reaches that code first—a race condition. The operating system cannot infer every rule the application needs, such as keeping one print job together. section 4.7 section 8.3 section 8.7

Several mechanisms can protect a shared resource:

  • An atomic operation cannot be observed by another thread in a partially completed state; it depends on hardware and runtime support. section 8.7
  • A lock permits access to protected code or data only while a task owns it. A mutex provides mutually exclusive access; a semaphore can permit several tasks at once. section 8.7

The dining philosophers

Five philosophers share chopsticks with their neighbors, and each needs two to eat. Treat each chopstick as a mutex: take the left, take the right, eat, then release both. The rules protect access, but they also reveal a danger: if tasks acquire locks that never become available, progress can stop. A lock is not a substitute for a sound acquisition-and-release plan. section 9.1

Synchronization can also order communication rather than protect memory. In a synchronous exchange, both parties must be ready and wait for the exchange to finish—like a phone conversation. With asynchronous messaging, a sender can move on and handle the reply later—more like texting. section 11.7

Use synchronization when tasks must share a resource or respect a dependency, but do not add it by default. Locks introduce delays and can limit scalability. Where possible, divide work into independent tasks or avoid shared memory through message passing; less coordination can mean simpler, faster-running programs. section 2.8 section 9.10

How Grokking Concurrency covers it

How deep it goes
Defines critical sections and compares atomic operations, locks, mutexes, and semaphores without implementing processor-level instructions.
Examples
Uses interleaved printer output and dining philosophers competing for chopsticks to make access rules and lock hazards concrete.
What it assumes
Defines critical sections and locks through shared-resource examples rather than assuming prior knowledge of synchronization.
What you can do after
Apply it via Python threading locks to protect shared resources while checking for stalled progress and synchronization costs.
How it connects
Connects task independence, race conditions, critical sections, deadlocks, and message passing.

Also explained in

Compare how 11 books explain synchronization →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Concurrency. The section links point to the parts of the book it draws on.