Semaphore Class

Last Updated on August 20, 2023 by KnownSense

semaphore controls access to a shared resource through the use of a counter.

  • If counter > 0, access to shared resources is provided.
  • If counter = 0, access to shared resources is denied.

What the counter is counting are permits that allow access to the shared resource. Thus, to access the resource, a thread must be granted a permit from the semaphore.

Synchronized allows only one thread of execution to access the resource at the same time. Semaphore allows up to n (you get to choose n) threads of execution to access the resource at the same time.

Characteristics of Semaphore

  • provides synchronization among the threads.
  • decreases the level of synchronization. Hence, provides a low-level synchronization mechanism.
  • does not contain a negative value. It holds a value that may either greater than zero or equal to zero.
  • We can implement semaphore using the test operation and interrupts, and we use the file descriptors for executing it.

Working of Semaphores

Constructors in Semaphore class

 There are two constructors in Semaphore class.

Semaphore(int num)
Semaphore(int num, boolean fair)

Here, num specifies the initial permit count. Thus, it specifies the number of threads that can access a shared resource at any one time. If it is one, then only one thread can access the resource at any one time. By default, all waiting threads are granted a permit in an undefined order. By setting fair to true, you can ensure that waiting threads are granted a permit in the order in which they requested access.

Semaphore provides two main methods for obtaining permits and releasing permits

  • acquire(): This method acquires a permit if one is available, and returns immediately, reducing the number of available permits by one. If the current thread is interrupted while waiting for a permit then InterruptedException is thrown.
  • release()Releases a permit, increasing the number of available permits by one. If any threads are trying to acquire a permit, then one is selected and given the permit that was just released. 

Types of Semaphores

There are four types of semaphores, which are as follows:

Counting Semaphore: Counting semaphore provides n number of permit because. To execute mutual exclusion or critical section where more than one but fixed number of thread is allowed to execute, a Counting semaphore can be used. 

public class CountingSemaphore {

    // Initialize the semaphore with the number
    // of permits required
    Semaphore counting = new Semaphore(2);

    public static void main(String args[])
    {
        final CountingSemaphore countingSemaphore = new CountingSemaphore();

        // Thread 1
        new Thread() {
            // Method that should be executed for thread1
            @Override public void run()
            {
                countingSemaphore.mutualExclusion();
            }
        }.start();

        // Thread 2
        new Thread() {
            // Method that should be executed for thread2
            @Override public void run()
            {
                countingSemaphore.mutualExclusion();
            }
        }.start();

        // Thread 3
        new Thread() {
            // Method that should be executed for thread2
            @Override public void run()
            {
                countingSemaphore.mutualExclusion();
            }
        }.start();
    }

    private void mutualExclusion()
    {
        // Try block to check for exceptions
        try {
            System.out.println(
                    Thread.currentThread().getName()
                            + "waiting for permits ");
            // acquire() acts as an input to semaphore
            // to check for available permits
            counting.acquire();
            // Mutual exclusive region
            System.out.println(
                    Thread.currentThread().getName()
                            + "acquire permits ");

            // sleep() method is used to hold thread for
            // sometime Parameter is nanoseconds to be
            // holded
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }

        finally {
            // release() method acts as output to semaphore
            // When thread operation is completed
            // release() method increase the permits
            // in the semaphore
            System.out.println(
                    Thread.currentThread().getName()
                            + " release permit ");
            counting.release();
        }
    }
}

output:
Thread-1waiting for permits 
Thread-2waiting for permits 
Thread-0waiting for permits 
Thread-1acquire permits 
Thread-2acquire permits 
Thread-1 release permit 
Thread-0acquire permits 
Thread-2 release permit 
Thread-0 release permit 

explanation: Here, we have 3 thread and 2 permits. So any 2 threads will acquire mutualExclusion code simultaneously and the third will wait for release by any one thread.

Binary Semaphore: 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. 
In above example replace “Semaphore counting = new Semaphore(2);” with “Semaphore counting = new Semaphore(1);” to make it binary.

Bounded Semaphores: We can set the upper bound limit using the bounded semaphores. It is used in place of the counting semaphores because the counting semaphores do not contain any upper bound value. The upper bound value denotes how many signals it can store.

public class BoundedSemaphore
{
  private int signal = 0;
  private int bound = 0;
  public BoundedSemaphore(int upperBound)
  {
    this.bound = upperBound;
}
public void synchronized take() throws InterruptedException
{
    while(this.signal == bound)
      wait();
      this.signal++;
      this.notify++;
}
public void synchronized release() throws InterruptedException
{
    while(this.signal == 0)
      wait();
      this.signal--;
  }
}

Timed Semaphores: The timed semaphores allow a thread to run for a specified period of time. After a particular time, the timer resets and releases all other permits.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top