11 Synchronization

 

This chapter covers

  • Single-threaded concurrency issues
  • Using locks to protect critical sections
  • Using semaphores to limit concurrency
  • Using events to notify tasks
  • Using conditions to notify tasks and acquire a resource

When we write applications using multiple threads and multiple processes, we need to worry about race conditions when using non-atomic operations. Something as simple as incrementing an integer concurrently can cause subtle, hard-to-reproduce bugs. When we are using asyncio, however, we’re always using a single thread (unless we’re interoperating with multithreading and multiprocessing), so doesn’t that mean we don’t need to worry about race conditions? It turns out it is not quite so simple.

While certain concurrency bugs that would occur in multithreaded or multiprocessing applications are eliminated by asyncio’s single-threaded nature, they are not completely eliminated. While you likely won’t need to use synchronization often with asyncio, there are still cases where we need these constructs. asyncio’s synchronization primitives can help us prevent bugs unique to a single-threaded concurrency model.

11.1 Understanding single-threaded concurrency bugs

11.2 Locks

11.3 Limiting concurrency with semaphores

11.3.1 Bounded semaphores

11.4 Notifying tasks with events

11.5 Conditions

Summary