The resources of a system are limited and have to be shared between the different processes. A resource must be used by one process at a given time and this is referred to as Process Synchronization. In Java, Semaphore is used to attain Process Synchronization. Semaphore in Java is a thread synchronization construct that avoids missed signals between threads by sending signals to the threads and protecting critical sections. With the use of counters, Semaphore manages access to the shared resources.  

What is Semaphore in Java?

Semaphore in Java is a variable that is used to manage processes that run in parallel. It is a non-negative variable that indicates the number of resources in the system that are available at a point in time. By using counters, the semaphore controls the shared resources to ensure that threads running simultaneously are able to access the resources and avoid race conditions. Thus the semaphore protects critical sections by using synchronized constructs. 

What Are the Types of Semaphore?

There are two types of Semaphore:

1. Counting Semaphore

The semaphore variable is initialized with the number of resources available. When a process needs to acquire a shared resource, wait() function is invoked and the value of the semaphore is reduced by 1. Once the process is done using the resource, it is released by invoking the signal() function. The value of the variable is increased by 1. When the semaphore value is 0, none of the resources are available and the process has to wait till a resource is released.

2. Binary Semaphore

In a binary semaphore, the value of the variable will be either 0 or 1. The value is set to 1 in the beginning and if a process wants to use a shared resource, it can invoke the wait() function, and the value changes from 1 to 0. Once the process is done using the resource, it is released by invoking the signal() function. The value of the variable changes from 0 to 1. When the value of the semaphore is 0 and a process has to wait to acquire the shared resource which has to be released by the previous process. 

How Does a Semaphore Work?

The counter of the semaphore holds a value of 0 or higher. 

  • When the value of the counter is greater than 0, the thread is allowed to access the shared resource and the counter value reduces by 1.
  • Otherwise until a permit can be obtained, the thread is blocked.
  • After the thread completes execution, it releases the resource that is no longer required. Once the resource is released, the counter value is increased by 1.
  • Another thread awaiting the acquisition of the same resource can now obtain a permit to access the resource. 
  • If the counter is 0, permission to access the resource is denied

The below flowchart indicates the working of Semaphore:

Semaphore_in_Java

Timed Semaphore

As the name indicates, a timed semaphore permits a thread to run for a specific amount of time. Once the time elapses, all permissions are released and the timer is reset. 

Semaphore vs. Mutex

Semaphore 

Mutex

Allows the shared resource to be used by multiple processes till it is available

Allows multiple processes to access a resource but 

It is a variable greater than 0

It is an object

Deploys signal mechanism where the methods wait() & signal() are used to indicate if a process is using a resource or releasing it

Deploys locking mechanism where the process using a resource locks it and releases it once it has finished using it

Multiple processes can change the value of a semaphore variable but only one process can modify it at a given time to acquire a resource

The same process can acquire or release a lock at a time

Implementation of Semaphore 

import java.util.concurrent.*;

//Will take Resource as shared class

class Resource

{

    static int count = 0;

class MyDemo extends Demo

{

    Semaphore sem;

    String threadName;

    public MyDemo(Semaphore sem, String threadName)

    {

        super(threadName);

        this.sem = sem;

        this.threadName = threadName;

    }

    @Override

    public void run() {   

        // Run By X

        if(this.getName().equals("X"))

        {

            System.out.println("Starting " + threadName);

            try

            {

                // Will get the permit to access shared resource

                System.out.println(threadName + " awaiting permit.");           

                // acquiring the lock

                sem.acquire();            

                System.out.println(threadName + " received a permit.");        

                // Now, accessing the shared resource and rest will wait 

                for(int i=0; i < 7; i++)

                {

                    Resource.count++;

                    System.out.println(threadName + ": " + Resouce.count);    

                    // Now thread Y will try  to execute

                    Thread.sleep(20);

                }

            } catch (InterruptedException exc) {

                    System.out.println(exc);

                }

                // Release the permit.

                System.out.println(threadName + " released permit.");

                sem.release();

        }         

        // run by thread Y

        else

        {

            System.out.println("Starting " + threadName);

            try

            {

                // First, Y will try to get permit

                System.out.println(threadName + " awaiting permit.");             

                // acquiring the lock

                sem.acquire();            

                System.out.println(threadName + " received a permit.");       

                // Now, accessing the shared resource and others will wait                 

                for(int i=0; i < 7; i++)

                {

                    Resource.count--;

                    System.out.println(threadName + ": " + Resource.count);         

                    // Now, allowing a context switch -- if possible.

                    // for thread X to execute

                    Thread.sleep(20);

                }

            } catch (InterruptedException exc) {

                    System.out.println(exc);

                }

                // Release the permit.

                System.out.println(threadName + " released permit.");

                sem.release();

        }

    }

}

public class SemTest

{

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

    {

        // creating a Semaphore object

        // with number of permits 1

        Semaphore sem = new Semaphore(1);         

        // creating two threads with name X and Y

        // Here thread X will increment and Y will decrement the counter

        MyDemo md1 = new MyDemo(sem, "X");

        MyDemo md2 = new MyDemo(sem, "Y");         

        // stating threads X and Y

        md1.start();

        md2.start();        

        // waiting for threads X and Y

        md1.join();

        mtd.join();    

        System.out.println("count: " + Resource.count);

    }

}

Output

Starting X

Starting Y

X awaiting permit

Y awaiting permit

X:1

X:2

X:3

X:4

X:5

X:6

X:7

X released permit

Y received a permit

Y:6

Y:5

Y:4

Y:3

Y:2

Y:1

Y:0

Y released permit

count:0

FAQs

1. What is the use of semaphore?

Semaphore is used to achieve process synchronization in Java. It uses a non-negative counter variable to provide access to the shared resource at a given time by a thread. The counter tracks the number of permissions provided to threads. 

2.What are two types of semaphore?

The two types of semaphore are

  1. Binary Semaphore: A semaphore with the value of 0 or 1 to manage parallel processes in sync and execute mutual exclusion. The value 1 indicates success and 0 indicates failure 
  2. Counting Semaphore: A semaphore that holds a value indicating the maximum number of processes that can enter the critical section simultaneously.  

3. Is a semaphore a queue?

A queue is an ordered linear data structure that follows the First in First Out (FIFO) principle. However, a semaphore does not ensure a specific order and is not a queue.  

4. What is semaphore and mutex in Java?

Mutex is a mutually exclusive object that controls access to a resource. It uses a locking mechanism to ensure that only one thread accesses the resource at a given time by entering the critical section. Once the thread exits the section, the resource is released by it. It is used to achieve process synchronization. 

Semaphore is also used for realizing process synchronization, however, it uses the signaling mechanism. By deploying a non-negative counter variable it shares signals between threads that need access to the same resource.

Conclusion

In this article we discussed Semaphore in Java and what are its uses. If you are looking to upskill further, then we highly recommend you to take up the Simplilearn’s Post Graduate Program in Full Stack Web Development. This course can help you hone the key Java skills and make you job ready with HIRIST and HackerEarth. Complete the course and get a guaranteed job with an average pay of 6.7 LPA.

If you have any doubts or queries regarding the article or the course, feel free to post them in the comments below. Our team will get back to you at the earliest.

Our Software Development Courses Duration And Fees

Software Development Course typically range from a few weeks to several months, with fees varying based on program and institution.

Program NameDurationFees
Caltech Coding Bootcamp

Cohort Starts: 16 Dec, 2024

6 Months$ 8,000
Automation Test Engineer Masters Program

Cohort Starts: 18 Dec, 2024

8 months$ 1,499
Full Stack Java Developer Masters Program

Cohort Starts: 18 Dec, 2024

7 months$ 1,449
Full Stack (MERN Stack) Developer Masters Program

Cohort Starts: 8 Jan, 2025

6 Months$ 1,449

Learn from Industry Experts with free Masterclasses

  • Key 2025 Software Development Trends- Learn How To Leverage them for your career

    Software Development

    Key 2025 Software Development Trends- Learn How To Leverage them for your career

    9th Dec, Monday9:30 PM IST
  • Must-Know Full Stack Java Dev Career Trends for 2024

    Software Development

    Must-Know Full Stack Java Dev Career Trends for 2024

    6th Aug, Tuesday9:00 PM IST
  • Full Stack Java Development: A 2024 Blueprint for Recession-Proofing Your Career

    Software Development

    Full Stack Java Development: A 2024 Blueprint for Recession-Proofing Your Career

    27th Jun, Thursday7:30 PM IST
prevNext