ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Semaphore.java
Revision: 1.4
Committed: Tue Jun 24 14:34:49 2003 UTC (20 years, 11 months ago) by dl
Branch: MAIN
Changes since 1.3: +11 -3 lines
Log Message:
Added missing javadoc tags; minor reformatting

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain. Use, modify, and
4     * redistribute this code in any way without acknowledgement.
5     */
6    
7 tim 1.1 package java.util.concurrent;
8    
9     /**
10     * A counting semaphore. Conceptually, a semaphore maintains a set of
11     * permits. Each {@link #acquire} blocks if necessary until a permit is
12     * available, and then takes it. Each {@link #release} adds a permit,
13     * potentially releasing a blocking acquirer.
14     * However, no actual permit objects are used; the <tt>Semaphore</tt> just
15     * keeps a count of the number available and acts accordingly.
16     *
17     * <p>Semaphores are used to restrict the number of threads than can
18     * access some (physical or logical) resource. For example, here is
19     * a class that uses a semaphore to control access to a pool of items:
20     * <pre>
21     * class Pool {
22     * private static final MAX_AVAILABLE = 100;
23     * private final Semaphore available = new Semaphore(MAX_AVAILABLE);
24     *
25     * public Object getItem() throws InterruptedException {
26     * available.acquire();
27     * return getNextAvailableItem();
28     * }
29     *
30     * public void putItem(Object x) {
31     * if (markAsUnused(x))
32     * available.release();
33     * }
34     *
35     * // Not a particularly efficient data structure; just for demo
36     *
37     * protected Object[] items = ... whatever kinds of items being managed
38     * protected boolean[] used = new boolean[MAX_AVAILABLE];
39     *
40     * protected synchronized Object getNextAvailableItem() {
41     * for (int i = 0; i < MAX_AVAILABLE; ++i) {
42     * if (!used[i]) {
43     * used[i] = true;
44     * return items[i];
45     * }
46     * }
47     * return null; // not reached
48     * }
49     *
50     * protected synchronized boolean markAsUnused(Object item) {
51     * for (int i = 0; i < MAX_AVAILABLE; ++i) {
52     * if (item == items[i]) {
53     * if (used[i]) {
54     * used[i] = false;
55     * return true;
56     * }
57     * else
58     * return false;
59     * }
60     * }
61     * return false;
62     * }
63     *
64     * }
65     * </pre>
66     * <p>Before obtaining an item each thread must acquire a permit from the
67     * semaphore, guaranteeing that an item is available for use. When the
68     * thread has finished with the item it is returned back to the pool and
69     * a permit is returned to the semaphore, allowing another thread to
70     * acquire that item.
71     * Note that no synchronization lock is held when {@link #acquire} is
72     * called as that would prevent an item from being returned to the pool.
73     * The semaphore encapsulates the synchronization needed to restrict access to
74     * the pool, separately from any synchronization needed to maintain the
75     * consistency of the pool itself.
76     *
77     * <p>A semaphore initialized to one, and which is used such that it only
78     * has at most one permit available, can serve as a mutual exclusion lock.
79     * This is more
80     * commonly known as a <em>binary semaphore</em>, because it only has two
81     * states: one permit available, or zero permits available.
82     * When used in this way, the binary semaphore has the property (unlike many
83     * {@link Lock} implementations, that the &quot;lock&quot; can be released by
84     * a thread other than the owner (as semaphores have no notion of ownership).
85     * This can be useful in some specialised contexts, such as deadlock recovery.
86     *
87     * <p>This class makes no guarantees about the order in which threads
88     * acquire permits. In particular, barging is permitted, that is, a thread
89     * invoking {@link #acquire} can be allocated a permit ahead of a thread
90     * that has been waiting. If you need more deterministic guarantees, consider
91 dl 1.3 * using {@link FairSemaphore}.
92 tim 1.1 *
93     *
94     * @since 1.5
95     * @spec JSR-166
96 dl 1.4 * @revised $Date: 2003/06/06 18:42:17 $
97 dl 1.3 * @editor $Author: dl $
98 dl 1.4 * @author Doug Lea
99 tim 1.1 *
100     */
101 dl 1.2 public class Semaphore implements java.io.Serializable {
102     // todo SerialID
103     // uses default serialization, which happens be fine here.
104    
105     // Fields are package-private to allow the FairSemaphore variant
106     // to access.
107    
108     final ReentrantLock lock;
109     final Condition available;
110     long count;
111 tim 1.1
112 dl 1.4 /**
113     * Package-private constructor used by FairSemaphore
114     * @param permits the initial number of permits available
115     * @param lock the lock to use
116     */
117 dl 1.2 Semaphore(long permits, ReentrantLock lock) {
118     this.count = permits;
119     this.lock = lock;
120     available = lock.newCondition();
121     }
122 tim 1.1
123     /**
124     * Construct a <tt>Semaphore</tt> with the given number of
125     * permits.
126     * @param permits the initial number of permits available
127     */
128     public Semaphore(long permits) {
129 dl 1.2 this(permits, new ReentrantLock());
130 tim 1.1 }
131    
132     /**
133     * Acquires a permit from this semaphore, blocking until one is
134     * available, or the thread is {@link Thread#interrupt interrupted}.
135     *
136     * <p>Acquires a permit, if one is available and returns immediately,
137     * reducing the number of available permits by one.
138     * <p>If no permit is available then the current thread becomes
139     * disabled for thread scheduling purposes and lies dormant until
140     * one of two things happens:
141     * <ul>
142     * <li>Some other thread invokes the {@link #release} method for this
143     * semaphore and the current thread happens to be chosen as the
144     * thread to receive the permit; or
145     * <li>Some other thread {@link Thread#interrupt interrupts} the current
146     * thread.
147     * </ul>
148     *
149     * <p>If the current thread:
150     * <ul>
151     * <li>has its interrupted status set on entry to this method; or
152     * <li>is {@link Thread#interrupt interrupted} while waiting
153     * for a permit,
154     * </ul>
155     * then {@link InterruptedException} is thrown and the current thread's
156     * interrupted status is cleared.
157     *
158     * @throws InterruptedException if the current thread is interrupted
159     *
160     * @see Thread#interrupt
161     */
162 dl 1.2 public void acquire() throws InterruptedException {
163     lock.lockInterruptibly();
164     try {
165 dl 1.4 while (count <= 0)
166     available.await();
167 dl 1.2 --count;
168     }
169     catch (InterruptedException ie) {
170     available.signal();
171     throw ie;
172     }
173     finally {
174     lock.unlock();
175     }
176     }
177 tim 1.1
178     /**
179     * Acquires a permit from this semaphore, blocking until one is
180     * available.
181     *
182     * <p>Acquires a permit, if one is available and returns immediately,
183     * reducing the number of available permits by one.
184     * <p>If no permit is available then the current thread becomes
185     * disabled for thread scheduling purposes and lies dormant until
186     * some other thread invokes the {@link #release} method for this
187     * semaphore and the current thread happens to be chosen as the
188     * thread to receive the permit.
189     *
190     * <p>If the current thread
191     * is {@link Thread#interrupt interrupted} while waiting
192     * for a permit then it will continue to wait, but the time at which
193     * the thread is assigned a permit may change compared to the time it
194     * would have received the permit had no interruption occurred. When the
195     * thread does return from this method its interrupt status will be set.
196     *
197     */
198 dl 1.2 public void acquireUninterruptibly() {
199     lock.lock();
200     try {
201 dl 1.4 while (count <= 0)
202     available.awaitUninterruptibly();
203 dl 1.2 --count;
204     }
205     finally {
206     lock.unlock();
207     }
208     }
209 tim 1.1
210     /**
211     * Acquires a permit from this semaphore, only if one is available at the
212     * time of invocation.
213     * <p>Acquires a permit, if one is available and returns immediately,
214     * with the value <tt>true</tt>,
215     * reducing the number of available permits by one.
216     *
217     * <p>If no permit is available then this method will return
218     * immediately with the value <tt>false</tt>.
219     *
220     * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
221     * otherwise.
222     */
223     public boolean tryAcquire() {
224 dl 1.2 lock.lock();
225     try {
226     if (count > 0) {
227     --count;
228     return true;
229     }
230     return false;
231     }
232     finally {
233     lock.unlock();
234     }
235 tim 1.1 }
236    
237     /**
238     * Acquires a permit from this semaphore, if one becomes available
239     * within the given waiting time and the
240     * current thread has not been {@link Thread#interrupt interrupted}.
241     * <p>Acquires a permit, if one is available and returns immediately,
242     * with the value <tt>true</tt>,
243     * reducing the number of available permits by one.
244     * <p>If no permit is available then
245     * the current thread becomes disabled for thread scheduling
246     * purposes and lies dormant until one of three things happens:
247     * <ul>
248     * <li>Some other thread invokes the {@link #release} method for this
249     * semaphore and the current thread happens to be chosen as the
250     * thread to receive the permit; or
251     * <li>Some other thread {@link Thread#interrupt interrupts} the current
252     * thread; or
253     * <li>The specified waiting time elapses.
254     * </ul>
255     * <p>If a permit is acquired then the value <tt>true</tt> is returned.
256     * <p>If the current thread:
257     * <ul>
258     * <li>has its interrupted status set on entry to this method; or
259     * <li>is {@link Thread#interrupt interrupted} while waiting to acquire
260     * a permit,
261     * </ul>
262     * then {@link InterruptedException} is thrown and the current thread's
263     * interrupted status is cleared.
264     * <p>If the specified waiting time elapses then the value <tt>false</tt>
265     * is returned.
266     * The given waiting time is a best-effort lower bound. If the time is
267     * less than or equal to zero, the method will not wait at all.
268     *
269     * @param timeout the maximum time to wait for a permit
270     * @param granularity the time unit of the <tt>timeout</tt> argument.
271     * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
272     * if the waiting time elapsed before a permit was acquired.
273     *
274     * @throws InterruptedException if the current thread is interrupted
275     *
276     * @see Thread#interrupt
277     *
278     */
279     public boolean tryAcquire(long timeout, TimeUnit granularity)
280     throws InterruptedException {
281 dl 1.2 lock.lockInterruptibly();
282     long nanos = granularity.toNanos(timeout);
283     try {
284     for (;;) {
285     if (count > 0) {
286     --count;
287     return true;
288     }
289     if (nanos <= 0)
290     return false;
291     nanos = available.awaitNanos(nanos);
292     }
293     }
294     catch (InterruptedException ie) {
295     available.signal();
296     throw ie;
297     }
298     finally {
299     lock.unlock();
300     }
301 tim 1.1 }
302    
303     /**
304     * Releases a permit, returning it to the semaphore.
305     * <p>Releases a permit, increasing the number of available permits
306     * by one.
307     * If any threads are blocking trying to acquire a permit, then one
308     * is selected and given the permit that was just released.
309     * That thread is re-enabled for thread scheduling purposes.
310     * <p>There is no requirement that a thread that releases a permit must
311     * have acquired that permit by calling {@link #acquire}.
312     * Correct usage of a semaphore is established by programming convention
313     * in the application.
314     */
315 dl 1.2 public void release() {
316     lock.lock();
317     try {
318     ++count;
319     available.signal();
320     }
321     finally {
322     lock.unlock();
323     }
324     }
325    
326 tim 1.1
327     /**
328     * Return the current number of permits available in this semaphore.
329     * <p>This method is typically used for debugging and testing purposes.
330     * @return the number of permits available in this semaphore.
331     */
332     public long availablePermits() {
333 dl 1.2 lock.lock();
334     try {
335     return count;
336     }
337     finally {
338     lock.unlock();
339     }
340 tim 1.1 }
341     }
342    
343    
344