Java Programming Concurrency Utilities Semaphore Countdownlatch Complete Guide

 Last Update:2025-06-22T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    7 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of Java Programming Concurrency Utilities Semaphore, CountDownLatch

Java Programming Concurrency Utilities: Semaphore, CountDownLatch

Semaphore

A Semaphore in Java is a concurrency control mechanism that allows multiple threads to access a common resource in a controlled manner. It maintains a set number of permits, which threads can acquire and release as they enter and exit the critical section of the code. Semaphores are particularly useful in scenarios where limited resources need to be shared among multiple threads.

Key Points:

  • Permits: Each semaphore has a maximum number of permits. Threads acquire permits to enter the critical section and release them when they are done.
  • Fairness: Semaphores can be created in "fair" mode, meaning that the semaphore will grant permits to waiting threads in the order in which they requested them.
  • Multiple Permits: You can acquire or release more than one permit at a time, making it flexible for various use cases.
  • Use Cases: Resource pooling, limiting concurrent execution, controlling resource access, etc.

Example Code:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private static final int MAX_PERMITS = 3;

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(MAX_PERMITS, true); // Fair Semaphore

        for (int i = 0; i < 5; i++) {
            new Thread(new Worker(semaphore, "Thread-" + i)).start();
        }
    }

    static class Worker implements Runnable {
        private final Semaphore semaphore;
        private final String name;

        public Worker(Semaphore semaphore, String name) {
            this.semaphore = semaphore;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire(); // Acquire a permit
                System.out.println(name + " has entered the critical section.");
                Thread.sleep(2000); // Simulate work
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                semaphore.release(); // Release the permit
                System.out.println(name + " has exited the critical section.");
            }
        }
    }
}

Explanation:

  • Semaphore Initialization: The semaphore is initialized with 3 permits, allowing up to 3 threads to enter the critical section simultaneously.
  • Thread Creation: Five threads are created, each trying to acquire a permit from the semaphore.
  • Acquire and Release: When a thread acquires a permit, it enters the critical section. After completing its task, it releases the permit, allowing other threads to enter.

CountDownLatch

A CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. It is used for coordinating multiple threads where one thread should wait for others to complete their tasks before proceeding.

Key Points:

  • Countdown: The count is initialized when the latch is created and can only be decremented. Once the count reaches zero, all waiting threads are allowed to proceed.
  • Threads: Any thread can decrement the count or wait for the latch to reach zero.
  • Use Cases: Thread synchronization, initialization of resources, waiting for multiple operations to complete, etc.

Example Code:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    private static final int NUM_WORKERS = 3;

    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(NUM_WORKERS);

        for (int i = 0; i < NUM_WORKERS; i++) {
            new Thread(new Worker(latch, "Thread-" + i)).start();
        }

        try {
            latch.await(); // Wait for all workers to finish
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        System.out.println("All workers have completed their tasks.");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;
        private final String name;

        public Worker(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(name + " is starting.");
                Thread.sleep(2000); // Simulate work
                System.out.println(name + " has finished.");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                latch.countDown(); // Decrement the count
            }
        }
    }
}

Explanation:

  • CountDownLatch Initialization: The latch is created with a count of 3, representing the number of worker threads.
  • Thread Creation: Three threads are created, each performing some work independently.
  • Await and CountDown: The main thread waits until the latch count is reduced to zero (all workers have completed their tasks), and then it proceeds with its execution.

Summary

In summary, Java's Semaphore and CountDownLatch are powerful concurrency utilities that enable developers to control thread access and synchronization effectively. Semaphore manages multiple permits to control the number of threads accessing a shared resource, while CountDownLatch allows one or more threads to wait until a set of operations performed in other threads completes. Both tools enhance the robustness and efficiency of concurrent Java applications.

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement Java Programming Concurrency Utilities Semaphore, CountDownLatch

Java Concurrency Utilities: Semaphore

What is a Semaphore?

A Semaphore controls access to multiple resources. If a semaphore is initialized with 3, it means at most 3 threads can access the controlled resource at a time.

Step-by-Step Example

  1. Create a Class for the Resource Accessing Tasks

    This class will implement the Runnable interface and represent the task to be executed.

  2. Use Semaphore in the Task

    We will use a Semaphore to control the access to this resource.

  3. Create and Execute Multiple Threads

    We will create multiple threads that will execute our task.

import java.util.concurrent.Semaphore;

class ResourceAccessingTask implements Runnable {
    private final Semaphore semaphore;
    private final String taskName;
    private final int duration;

    public ResourceAccessingTask(Semaphore semaphore, String taskName, int duration) {
        this.semaphore = semaphore;
        this.taskName = taskName;
        this.duration = duration;
    }

    @Override
    public void run() {
        try {
            // Acquire the semaphore lock
            System.out.println(taskName + " is waiting to acquire lock...");
            semaphore.acquire();
            System.out.println(taskName + " has acquired lock...");

            // Simulate resource access
            System.out.println(taskName + " is accessing resource...");
            Thread.sleep(duration * 1000); // Simulate resource processing time
            System.out.println(taskName + " is done with resource...");

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println(taskName + " thread was interrupted");

        } finally {
            // Release the semaphore lock
            System.out.println(taskName + " is releasing lock...");
            semaphore.release();
        }
    }
}

public class SemaphoreExample {
    public static void main(String[] args) {
        // Create a Semaphore with a permit count of 3
        Semaphore semaphore = new Semaphore(3);

        // Create and start multiple threads
        for (int i = 1; i <= 5; i++) {
            String taskName = "Task-" + i;
            int duration = (i % 3) + 1; // Random durations
            Thread thread = new Thread(new ResourceAccessingTask(semaphore, taskName, duration));
            thread.start();
        }
    }
}

Explanation:

  • Semaphore Initialization: Semaphore semaphore = new Semaphore(3); initializes a semaphore with 3 permits, meaning up to 3 threads can access the resource concurrently.
  • Task Implementation: The ResourceAccessingTask class implements Runnable and uses the semaphore to manage access to the resource.
  • Task Execution: The main method creates and starts five threads, where each thread runs an instance of ResourceAccessingTask. The first three threads will acquire a permit immediately, and the threads will wait if no permits are available.

Java Concurrency Utilities: CountDownLatch

What is a CountDownLatch?

A CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

Step-by-Step Example

  1. Create a Class for the Worker Tasks

    This class will implement the Runnable interface and represent the worker tasks.

  2. Use CountDownLatch in the Worker Tasks

    We will use a CountDownLatch to ensure that the main thread waits for all worker threads to complete.

  3. Main Thread to Wait

    The main thread will wait for the worker threads using CountDownLatch.

Top 10 Interview Questions & Answers on Java Programming Concurrency Utilities Semaphore, CountDownLatch

1. What is a Semaphore in Java, and how does it work?

Answer: A Semaphore in Java is a signaling construct that allows multiple threads to access a shared resource concurrently up to a certain limit. It uses a set number of permits, which can be acquired by threads before access is granted. When a thread releases the permit, it becomes available for another thread to use. This is useful for controlling access to a finite pool of resources, such as database connections.

2. How do you create a Semaphore in Java?

Answer: You can create a Semaphore by instantiating it with the number of permits. For example:

Semaphore semaphore = new Semaphore(5); // Allows up to 5 threads to access the resource

You can also specify whether the semaphore should be fair or not:

Semaphore semaphore = new Semaphore(5, true); // Fairness parameter is true

3. What is the difference between acquire() and tryAcquire() methods in Semaphore?

Answer:

  • acquire(): This method blocks the calling thread until a permit is available. If there are no available permits, the thread is added to a queue and waits until a permit becomes available.
  • tryAcquire(): This method attempts to acquire a permit immediately without blocking. It returns true if a permit was acquired and false otherwise.

4. What is a CountDownLatch in Java?

Answer: A CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations, being performed in other threads, completes. It uses a count-down counter, initialized to a given value. Each time the countDown() method is called, the count is decremented. When the count reaches zero, all waiting threads are released.

5. How do you create a CountDownLatch and use it?

Answer: You create a CountDownLatch by specifying the number of times countDown() must be called before threads can pass through. For example:

CountDownLatch latch = new CountDownLatch(3); // Initialize with 3 count-downs

Threads waiting on the latch will block until the latch count reaches zero:

latch.await(); // Blocks until the count reaches zero

Threads that perform the required operations can count down:

latch.countDown(); // Decrements the count by 1

6. Can a CountDownLatch be reused?

Answer: No, a CountDownLatch is a single-use object. Once the count reaches zero, it cannot be reset. If you need to reset the count, consider using a CyclicBarrier instead.

7. What are some common use cases for Semaphore and CountDownLatch in real-world applications?

Answer:

  • Semaphore: Controlling access to limited resources, such as database connections or thread pools.
  • CountDownLatch: Synchronizing threads to wait for multiple operations to complete, such as waiting for all worker threads to finish processing.

8. How can Semaphore and CountDownLatch handle exceptions?

Answer:

  • Semaphore: If a thread waiting on acquire() or acquireInterruptibly() is interrupted, it throws an InterruptedException.
  • CountDownLatch: If a thread waiting on await() is interrupted, it throws an InterruptedException.

9. Can a Semaphore be initialized to a negative value?

Answer: No, a Semaphore cannot be initialized to a negative value. If you try to do so, it will throw an IllegalArgumentException.

10. What is the difference between CyclicBarrier and CountDownLatch?

Answer:

  • CountDownLatch: It allows one or more threads to wait until a set of operations, being performed in other threads, completes. Once the count reaches zero, it cannot be reused.
  • CyclicBarrier: It allows a set of threads to wait for each other to reach a common barrier point. Unlike CountDownLatch, a CyclicBarrier can be reused after the barrier is broken. It can also optionally perform a barrier action when the specified number of parties have arrived at the barrier.

You May Like This Related .NET Topic

Login to post a comment.