Open In App

How to Use Counting Semaphore in Concurrent Java Application?

Java Counting Semaphore maintains a specified number of passes or permissions, and the Current Thread must obtain a permit to access a shared resource. If a permit is already exhausted by threads other than that, it may wait until the permit becomes available as a result of the release of permits from various threads. This concurrency utility can be very useful for implementing a pattern of producer-consumer design or implementing limited pools of assets such as Thread Pool, DB Connection Pool, etc. The class java.util.Semaphore is a Counting Semaphore that is initialized with a number of permissions. 

How to Use Counting Semaphore in Concurrent Java Application?

Semaphore provides two main methods for obtaining permits and releasing permits

Implementation:

A binary semaphore is known as a Counting semaphore with one permit because it only has two state permits available or unavailable permits. To execute mutual exclusion or critical section where only one thread is allowed to execute, a binary semaphore can be used. A thread waits on acquire() until Thread allows release within the critical section by calling release() on the semaphore. Below is java semaphore counting where binary semaphore is used to provide shared exclusive access to essential code parts

Example:

import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    // Create a semaphore with a single permit
    Semaphore binary = new Semaphore(1);

    public static void main(String args[]) {
        final SemaphoreTest test = new SemaphoreTest();

        // Create and start the first thread
        new Thread() {
            @Override public void run() {
                test.mutualExclusion();
            }
        }.start();

        // Create and start the second thread
        new Thread() {
            @Override public void run() {
                test.mutualExclusion();
            }
        }.start();
    }

    private void mutualExclusion() {
        try {
            // Try to acquire the semaphore
            binary.acquire();

            // Synchronized block to ensure sequential printing for each thread
            synchronized (System.out) {
                // Print a message indicating that the current thread is inside the mutual exclusive region
                System.out.println(Thread.currentThread().getName() + " inside mutual exclusive ");
            }

            // Make the current thread sleep for 1 second
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // Print the stack trace for the InterruptedException
            e.printStackTrace();
        } finally {
            // Release the semaphore
            binary.release();

            // Synchronized block to ensure sequential printing for each thread
            synchronized (System.out) {
                // Print a message indicating that the current thread is outside the mutual exclusive region
                System.out.println(Thread.currentThread().getName() + " outside of mutual exclusive ");
            }
        }
    }
}

Output
Thread-0 inside mutual exclusive 
Thread-1 inside mutual exclusive 
Thread-0 outside of mutual exclusive 
Thread-1 outside of mutual exclusive 
Article Tags :