java.util.concurrent
Class Semaphore

java.lang.Object
  extended byjava.util.concurrent.Semaphore
All Implemented Interfaces:
java.io.Serializable
Direct Known Subclasses:
FairSemaphore

public class Semaphore
extends java.lang.Object
implements java.io.Serializable

A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

Semaphores are used to restrict the number of threads than can access some (physical or logical) resource. For example, here is a class that uses a semaphore to control access to a pool of items:

 class Pool {
   private static final MAX_AVAILABLE = 100;
   private final Semaphore available = new Semaphore(MAX_AVAILABLE);

   public Object getItem() throws InterruptedException {
     available.acquire();
     return getNextAvailableItem();
   }

   public void putItem(Object x) {
     if (markAsUnused(x))
       available.release();
   }

   // Not a particularly efficient data structure; just for demo

   protected Object[] items = ... whatever kinds of items being managed
   protected boolean[] used = new boolean[MAX_AVAILABLE];

   protected synchronized Object getNextAvailableItem() {
     for (int i = 0; i < MAX_AVAILABLE; ++i) {
       if (!used[i]) {
          used[i] = true;
          return items[i];
       }
     }
     return null; // not reached
   }

   protected synchronized boolean markAsUnused(Object item) {
     for (int i = 0; i < MAX_AVAILABLE; ++i) {
       if (item == items[i]) {
          if (used[i]) {
            used[i] = false;
            return true;
          } else
            return false;
       }
     }
     return false;
   }

 }
 

Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an item is available for use. When the thread has finished with the item it is returned back to the pool and a permit is returned to the semaphore, allowing another thread to acquire that item. Note that no synchronization lock is held when acquire() is called as that would prevent an item from being returned to the pool. The semaphore encapsulates the synchronization needed to restrict access to the pool, separately from any synchronization needed to maintain the consistency of the pool itself.

A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations, that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.

This class makes no guarantees about the order in which threads acquire permits. In particular, barging is permitted, that is, a thread invoking acquire() can be allocated a permit ahead of a thread that has been waiting. If you need more deterministic guarantees, consider using FairSemaphore.

Since:
1.5
Author:
Doug Lea
See Also:
Serialized Form

Constructor Summary
Semaphore(long permits)
          Construct a Semaphore with the given number of permits.
 
Method Summary
 void acquire()
          Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted.
 void acquireUninterruptibly()
          Acquires a permit from this semaphore, blocking until one is available.
 long availablePermits()
          Return the current number of permits available in this semaphore.
 void release()
          Releases a permit, returning it to the semaphore.
 boolean tryAcquire()
          Acquires a permit from this semaphore, only if one is available at the time of invocation.
 boolean tryAcquire(long timeout, TimeUnit granularity)
          Acquires a permit from this semaphore, if one becomes available within the given waiting time and the current thread has not been interrupted.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Semaphore

public Semaphore(long permits)
Construct a Semaphore with the given number of permits.

Parameters:
permits - the initial number of permits available
Method Detail

acquire

public void acquire()
             throws java.lang.InterruptedException
Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted.

Acquires a permit, if one is available and returns immediately, reducing the number of available permits by one.

If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens:

If the current thread:

then InterruptedException is thrown and the current thread's interrupted status is cleared.

Throws:
java.lang.InterruptedException - if the current thread is interrupted
See Also:
Thread.interrupt()

acquireUninterruptibly

public void acquireUninterruptibly()
Acquires a permit from this semaphore, blocking until one is available.

Acquires a permit, if one is available and returns immediately, reducing the number of available permits by one.

If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant until some other thread invokes the release() method for this semaphore and the current thread happens to be chosen as the thread to receive the permit.

If the current thread is interrupted while waiting for a permit then it will continue to wait, but the time at which the thread is assigned a permit may change compared to the time it would have received the permit had no interruption occurred. When the thread does return from this method its interrupt status will be set.


tryAcquire

public boolean tryAcquire()
Acquires a permit from this semaphore, only if one is available at the time of invocation.

Acquires a permit, if one is available and returns immediately, with the value true, reducing the number of available permits by one.

If no permit is available then this method will return immediately with the value false.

Returns:
true if a permit was acquired and false otherwise.

tryAcquire

public boolean tryAcquire(long timeout,
                          TimeUnit granularity)
                   throws java.lang.InterruptedException
Acquires a permit from this semaphore, if one becomes available within the given waiting time and the current thread has not been interrupted.

Acquires a permit, if one is available and returns immediately, with the value true, reducing the number of available permits by one.

If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:

If a permit is acquired then the value true is returned.

If the current thread:

then InterruptedException is thrown and the current thread's interrupted status is cleared.

If the specified waiting time elapses then the value false is returned. If the time is less than or equal to zero, the method will not wait at all.

Parameters:
timeout - the maximum time to wait for a permit
granularity - the time unit of the timeout argument.
Returns:
true if a permit was acquired and false if the waiting time elapsed before a permit was acquired.
Throws:
java.lang.InterruptedException - if the current thread is interrupted
See Also:
Thread.interrupt()

release

public void release()
Releases a permit, returning it to the semaphore.

Releases a permit, increasing the number of available permits by one. If any threads are blocking trying to acquire a permit, then one is selected and given the permit that was just released. That thread is re-enabled for thread scheduling purposes.

There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.


availablePermits

public long availablePermits()
Return the current number of permits available in this semaphore.

This method is typically used for debugging and testing purposes.

Returns:
the number of permits available in this semaphore.