Monday, May 21, 2012

Counting Semaphore Example in Java 5 – Concurrency Tutorial

Counting Semaphore in Java is a synchronizer which allows to impose a bound on resource is added in Java 5 along with other popular concurrent utilities like CountDownLatch, CyclicBarrier and Exchanger etc. Counting Semaphore in Java maintains specified number of pass or permits, In order to access a shared resource, Current Thread must acquire a permit. If permit is already exhausted by other thread than it can wait until a permit is available due to release of permit from different thread. This concurrency utility can be very useful to implement producer consumer design pattern or implement bounded pool or resources like Thread Pool, DB Connection pool etc. java.util.Semaphore class represent a Counting semaphore which is initialized with number of permits. Semaphore provides two main method acquire() and release() for getting permits and releasing permits. acquire() method blocks until permit is available. Semaphore provides both blocking method as well as unblocking method to acquire permits. This Java concurrency tutorial focus on a very simple example of Binary Semaphore and demonstrate how mutual exclusion can be achieved using Semaphore in Java.

Counting Semaphore Example in Java (Binary Semaphore)

Java 5 Semaphore Example codea Counting semaphore with one permit is known as binary semaphore because it has only two state permit available or permit unavailable. Binary semaphore can be used to implement mutual exclusion or critical section where only one thread is allowed to execute. Thread will wait on acquire() until Thread inside critical section release permit by calling release() on semaphore.

here is a simple example of counting semaphore in Java where we are using binary semaphore to provide mutual exclusive access on critical section of code in java:

import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    Semaphore binary = new Semaphore(1);
 
    public static void main(String args[]) {
        final SemaphoreTest test = new SemaphoreTest();
        new Thread(){
            @Override
            public void run(){
              test.mutualExclusion();
            }
        }.start();
     
        new Thread(){
            @Override
            public void run(){
              test.mutualExclusion();
            }
        }.start();
     
    }
 
    private void mutualExclusion() {
        try {
            binary.acquire();

            //mutual exclusive region
            System.out.println(Thread.currentThread().getName() + " inside mutual exclusive region");
            Thread.sleep(1000);

        } catch (InterruptedException i.e.) {
            ie.printStackTrace();
        } finally {
            binary.release();
            System.out.println(Thread.currentThread().getName() + " outside of mutual exclusive region");
        }
    }
 
}

Output:
Thread-0 inside mutual exclusive region
Thread-0 outside of mutual exclusive region
Thread-1 inside mutual exclusive region
Thread-1 outside of mutual exclusive region

Some Scenario where Semaphore can be used:
1) To implement better Database connection pool which will block if no more connection is available instead of failing and handover Connection as soon as its available.

2) To put a bound on collection classes. by using semaphore you can implement bounded collection whose bound is specified by counting semaphore.

That's all on Counting semaphore example in Java. Semaphore is real nice concurrent utility which can greatly simply design and implementation of bounded resource pool. Java 5 has added several useful  concurrent utility and deserve a better attention than casual look.

Important points of Counting Semaphore in Java

1. Semaphore class supports various overloaded version of tryAquire() method which acquires permit from semaphore only if its available during time of call.

2. Another worth noting method from Semaphore is acquireUninterruptibly() which is a blocking call and wait until a permit is available.

Other Java concurrency tutorial you may like

 
References

3 comments :

Anonymous said...

Hy there,

you didn't mention what the expected outcome is. If the expected outcome is to always get an "inside" and then an "outside", it would be wrong.

In the example it actually should never happen. But if you had more threads started or you do not wait, you will get "inside" "inside"...

maxx

Anonymous said...

to get the mentioned output make mutualExclusion method synchronized.

Anonymous said...

include sysout before release.

Post a Comment