|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectjava.util.concurrent.Semaphore
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.
| 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 |
public Semaphore(long permits)
permits - the initial number of permits available| Method Detail |
public void acquire()
throws java.lang.InterruptedException
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:
release() method for this
semaphore and the current thread happens to be chosen as the
thread to receive the permit; or
interrupts the current
thread.
If the current thread:
interrupted while waiting
for a permit,
InterruptedException is thrown and the current thread's
interrupted status is cleared.
java.lang.InterruptedException - if the current thread is interruptedThread.interrupt()public void acquireUninterruptibly()
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.
public boolean tryAcquire()
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.
public boolean tryAcquire(long timeout,
TimeUnit granularity)
throws java.lang.InterruptedException
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:
release() method for this
semaphore and the current thread happens to be chosen as the
thread to receive the permit; or
interrupts the current
thread; or
If a permit is acquired then the value true is returned.
If the current thread:
interrupted while waiting to acquire
a permit,
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.
timeout - the maximum time to wait for a permitgranularity - the time unit of the timeout argument.
java.lang.InterruptedException - if the current thread is interruptedThread.interrupt()public void release()
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.
public long availablePermits()
This method is typically used for debugging and testing purposes.
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||