Skip to content

semaphore

A semaphore is a synchronization primitive that controls access to a shared resource by keeping a counter of how many units of that resource remain available to concurrent threads or processes.

A thread decrements the counter before using the resource and increments it when finished. That gives the counter a simple acquire and release cycle, with a wait when no unit is free:

On acquire, a thread uses the resource if the counter is above zero, or blocks until another thread's release frees a unit.
Acquire, Release, and Block When No Unit Is Free

The counter is adjusted by two atomic operations that are often called acquire and release.

Semaphores take two common forms:

  • Counting semaphore: Lets the counter hold any non-negative value, which fits a pool of interchangeable resources such as a fixed set of database connections or download slots.
  • Binary semaphore: Caps the counter at one, so it behaves like a simple lock that is either held or free.

A binary semaphore resembles a mutex, but the two differ in ownership. Only the thread that acquired a mutex may release it, whereas any thread can signal a semaphore. That freedom makes semaphores a natural fit for the producer-consumer problem.

Careless use of semaphores may cause bugs because a unit that is acquired but never released can starve other waiting threads. Python provides semaphores through its threading and asyncio modules.

Python Thread Safety: Using a Lock and Other Techniques

Tutorial

Python Thread Safety: Using a Lock and Other Techniques

In this tutorial, you'll learn about the issues that can occur when your code is run in a multithreaded environment. Then you'll explore the various synchronization primitives available in Python's threading module, such as locks, which help you make your code safe.

intermediate python stdlib

For additional information on related topics, take a look at the following resources:


By Martin Breuss • Updated June 22, 2026 • Reviewed by Leodanis Pozo Ramos