package java.util.concurrent; /** * A counting semaphore. Conceptually, a semaphore maintains a set of * permits. Each {@link #acquire} blocks if necessary until a permit is * available, and then takes it. Each {@link #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 {@link #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 * {@link 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 specialised 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 {@link #acquire} can be allocated a permit ahead of a thread * that has been waiting. If you need more deterministic guarantees, consider * using {@link FifoSemaphore}. * * * @since 1.5 * @spec JSR-166 * @revised $Date: 2003/05/14 21:30:48 $ * @editor $Author: tim $ * */ public class Semaphore { private long permits = 0; /** * Construct a Semaphore with the given number of * permits. * @param permits the initial number of permits available */ public Semaphore(long permits) { this.permits = permits; } /** * Acquires a permit from this semaphore, blocking until one is * available, or the thread is {@link Thread#interrupt 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: *
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 {@link #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 {@link Thread#interrupt 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. * */ public void acquireUninterruptibly() {} /** * 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. * * @return true if a permit was acquired and false * otherwise. */ public boolean tryAcquire() { return false; } /** * Acquires a permit from this semaphore, if one becomes available * within the given waiting time and the * current thread has not been {@link Thread#interrupt 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: *
If the specified waiting time elapses then the value false * is returned. * The given waiting time is a best-effort lower bound. If the time is * less than or equal to zero, the method will not wait at all. * * @param timeout the maximum time to wait for a permit * @param granularity the time unit of the timeout argument. * @return true if a permit was acquired and false * if the waiting time elapsed before a permit was acquired. * * @throws InterruptedException if the current thread is interrupted * * @see Thread#interrupt * */ public boolean tryAcquire(long timeout, TimeUnit granularity) throws InterruptedException { return false; } /** * 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 {@link #acquire}. * Correct usage of a semaphore is established by programming convention * in the application. */ public void release() {} /** * Return the current number of permits available in this semaphore. *
This method is typically used for debugging and testing purposes. * @return the number of permits available in this semaphore. */ public long availablePermits() { return permits; } }