DEV Community

Cover image for Understanding Semaphores in Java – A Beginner's Guide
SRIMATHI K R
SRIMATHI K R

Posted on

Understanding Semaphores in Java – A Beginner's Guide

Imagine you and your friends are waiting to use a washing machine.

  • If there is only one washing machine, only one person can use it at a time.
  • If there are five washing machines, then five people can use them simultaneously.

This is exactly what a Semaphore does in programming.

A Semaphore is a synchronization mechanism that limits the number of threads that can access a shared resource simultaneously.


Key Concepts

  • A Semaphore uses permits.
  • acquire() takes a permit. If no permits are available, the thread waits.
  • release() returns a permit back to the semaphore.
  • Semaphore(5) allows up to 5 concurrent threads to access a shared resource.

Producer-Consumer

The Producer-Consumer Problem is one of the most common use cases of semaphores.

  • A Producer creates items and places them into a shared buffer.
  • A Consumer removes items from the shared buffer.

Semaphores coordinate access so that:

  • The producer does not overfill the buffer.
  • The consumer does not consume from an empty buffer.

This ensures proper synchronization between producer and consumer threads.


Mutex vs Semaphore

Mutex

A Mutex allows only one thread to access the critical section at a time.

Characteristics

  • Only ONE thread can enter the critical section.
  • Used for mutual exclusion.
  • Prevents race conditions by ensuring exclusive access to shared resources.

Semaphore

A Semaphore allows multiple threads to access a shared resource based on the number of permits available.

Characteristics

  • Allows multiple threads simultaneously.
  • The number of concurrent threads depends on the number of permits.
  • Example: Semaphore(5) allows up to 5 threads to access the resource at the same time.

Java Example

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

    public static void main(String[] args) throws InterruptedException {

        Semaphore semaphore = new Semaphore(5);

        semaphore.acquire();

        // Critical section
        System.out.println("Thread is accessing the shared resource.");

        semaphore.release();
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

  • Use a Mutex when only one thread should access a shared resource at a time.
  • Use a Semaphore when a limited number of threads can access the resource simultaneously.

Common real-world use cases include:

  • Database connection pools
  • Printer management
  • Thread pools
  • API rate limiting
  • Parking lot simulations
  • Producer-Consumer systems

Semaphores help efficiently manage concurrent access to shared resources while preventing conflicts and improving application performance.

Top comments (0)