Java Semaphore Example

0

A Semaphore controls access to shared resources by maintaining a count of permits.

The count of permit is passed to the Semaphore during its initialization. Semaphore doesn’t use any actual permit object and just depends on the count of the number available. If one wants to access the resource,

Semaphore allows only if the internal count is greater than zero. A count of zero means, there is no resource available and someone holding the resource must release for the Semaphore to allow further access. In this article, we look into an example of Semaphore and its APIs.

Semaphore Acquire and Release APIs

Let’s go through the APIs Semaphore provides for acquiring and releasing the resource.

  1. acquire() We will use this to acquire resource from a Semaphore. The internal count will get decremented by 1. If the counter is zero, the thread waits until the counter is non-zero.
  2. tryAcquire() This is similar to acquire, if no permit is available, instead of blocking, this method will return immediately with the value false. If able to acquire the resource, it will return with value true
  3. release() Call this when you are done with the resource, it will increment the resource availability counter.

Semaphore Example

In our example, we use Semaphore to control number of concurrent players in a gaming software.

For a user to join the game, its mandatory to acquire a permit from the Semaphore. Class SoftwareGroupLicense represents a group license. We pass the no. of concurrent players allowed. When a user exists the game, the permit is returned back to the Semaphore. If all licenses are in use, the permit count would be zero in which case UsersExceededException is thrown.

SoftwareGroupLicense:

package com.javarticles.concurrency;

import java.util.concurrent.Semaphore;

public class SoftwareGroupLicense {
    private Semaphore licenses;
    public SoftwareGroupLicense(int count) {
        licenses = new Semaphore(count);
    }
    
    public void join() {
        if (!licenses.tryAcquire()) {
            throw new UsersExceededException("All licenses are in use");
        }       
        System.out.println("Licenses left " + getAvailableLicenses());
    }
    
    public void exit() {
        licenses.release();
        System.out.println("Licenses left " + licenses.availablePermits());
    }
    
    public int getAvailableLicenses() {
        return licenses.availablePermits();
    }
}

GamingUser:

package com.javarticles.concurrency;

public class GamingUser {
    private SoftwareGroupLicense groupLicense;
    private String name;

    public GamingUser(String name, SoftwareGroupLicense groupLicense) {
        this.name = name;
        this.groupLicense = groupLicense;
    }

    public void join() {
        System.out.println(name + " joins");
        groupLicense.join();
    }

    public void exit() {
        System.out.println(name + " exists");
        groupLicense.exit();
    }
}

UsersExceededException:

package com.javarticles.concurrency;

public class UsersExceededException extends RuntimeException {

    public UsersExceededException(String msg) {
        super(msg);
    }
}

Let’s test our Semaphore. We create group license of five concurrent users. Next, we create a gaming user, pass the shared license object to it. When user joins, we call sempahore.tryAcquire(). When user exists, we call semaphore.release().

SemaphoreExample:

package com.javarticles.concurrency;

public class SemaphoreExample {   
    public static void main(String[] args) {
        SoftwareGroupLicense groupLicense = new SoftwareGroupLicense(5);
        System.out.println("No. of licenses available: " + groupLicense.getAvailableLicenses());
        GamingUser user1 = new GamingUser("User1" , groupLicense);
        user1.join();
        GamingUser user2 = new GamingUser("User2" , groupLicense);
        user2.join();
        GamingUser user3 = new GamingUser("User3" , groupLicense);
        user3.join();
        GamingUser user4 = new GamingUser("User4" , groupLicense);
        user4.join();
        GamingUser user5 = new GamingUser("User5" , groupLicense);
        user5.join();
        GamingUser user6 = new GamingUser("User6" , groupLicense);
        try {
            user6.join();
        } catch (UsersExceededException e) {
            System.out.println(e.getMessage());
            user1.exit();           
        }
        
    }
}

Output:

No. of licenses available: 5
User1 joins
Licenses left 4
User2 joins
Licenses left 3
User3 joins
Licenses left 2
User4 joins
Licenses left 1
User5 joins
Licenses left 0
User6 joins
All licenses are in use
User1 exists
Licenses left 1

Download the source code

This was an example about Java Semaphore.

You can download the source code here: javaSemaphoreExample.zip
Share.

Comments are closed.