ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Semaphore.java
Revision: 1.14
Committed: Sat Oct 11 15:37:31 2003 UTC (20 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.13: +1 -1 lines
Log Message:
Redeclare some Conditions as ReentrantLock.ConditionObjects

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 dl 1.5 import java.util.concurrent.locks.*;
9 tim 1.1
10     /**
11     * A counting semaphore. Conceptually, a semaphore maintains a set of
12     * permits. Each {@link #acquire} blocks if necessary until a permit is
13     * available, and then takes it. Each {@link #release} adds a permit,
14     * potentially releasing a blocking acquirer.
15     * However, no actual permit objects are used; the <tt>Semaphore</tt> just
16     * keeps a count of the number available and acts accordingly.
17     *
18     * <p>Semaphores are used to restrict the number of threads than can
19     * access some (physical or logical) resource. For example, here is
20     * a class that uses a semaphore to control access to a pool of items:
21     * <pre>
22     * class Pool {
23     * private static final MAX_AVAILABLE = 100;
24     * private final Semaphore available = new Semaphore(MAX_AVAILABLE);
25     *
26     * public Object getItem() throws InterruptedException {
27     * available.acquire();
28     * return getNextAvailableItem();
29     * }
30     *
31     * public void putItem(Object x) {
32     * if (markAsUnused(x))
33     * available.release();
34     * }
35     *
36     * // Not a particularly efficient data structure; just for demo
37     *
38     * protected Object[] items = ... whatever kinds of items being managed
39     * protected boolean[] used = new boolean[MAX_AVAILABLE];
40     *
41     * protected synchronized Object getNextAvailableItem() {
42     * for (int i = 0; i < MAX_AVAILABLE; ++i) {
43     * if (!used[i]) {
44     * used[i] = true;
45     * return items[i];
46     * }
47     * }
48     * return null; // not reached
49     * }
50     *
51     * protected synchronized boolean markAsUnused(Object item) {
52     * for (int i = 0; i < MAX_AVAILABLE; ++i) {
53     * if (item == items[i]) {
54     * if (used[i]) {
55     * used[i] = false;
56     * return true;
57 tim 1.8 * } else
58 tim 1.1 * 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 dl 1.12 * This can be useful in some specialized contexts, such as deadlock recovery.
86 tim 1.1 *
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 dl 1.4 * @author Doug Lea
96 tim 1.1 *
97     */
98 dl 1.2 public class Semaphore implements java.io.Serializable {
99 dl 1.9 private static final long serialVersionUID = 3217036696412297181L;
100    
101 dl 1.2
102     // Fields are package-private to allow the FairSemaphore variant
103     // to access.
104    
105     final ReentrantLock lock;
106 dl 1.14 final ReentrantLock.ConditionObject available;
107 dl 1.2 long count;
108 tim 1.1
109 dl 1.4 /**
110     * Package-private constructor used by FairSemaphore
111     * @param permits the initial number of permits available
112     * @param lock the lock to use
113     */
114 dl 1.2 Semaphore(long permits, ReentrantLock lock) {
115     this.count = permits;
116     this.lock = lock;
117     available = lock.newCondition();
118     }
119 tim 1.1
120     /**
121     * Construct a <tt>Semaphore</tt> with the given number of
122     * permits.
123     * @param permits the initial number of permits available
124     */
125     public Semaphore(long permits) {
126 dl 1.2 this(permits, new ReentrantLock());
127 tim 1.1 }
128    
129     /**
130     * Acquires a permit from this semaphore, blocking until one is
131     * available, or the thread is {@link Thread#interrupt interrupted}.
132     *
133     * <p>Acquires a permit, if one is available and returns immediately,
134     * reducing the number of available permits by one.
135     * <p>If no permit is available then the current thread becomes
136     * disabled for thread scheduling purposes and lies dormant until
137     * one of two things happens:
138     * <ul>
139     * <li>Some other thread invokes the {@link #release} method for this
140     * semaphore and the current thread happens to be chosen as the
141     * thread to receive the permit; or
142     * <li>Some other thread {@link Thread#interrupt interrupts} the current
143     * thread.
144     * </ul>
145     *
146     * <p>If the current thread:
147     * <ul>
148     * <li>has its interrupted status set on entry to this method; or
149     * <li>is {@link Thread#interrupt interrupted} while waiting
150     * for a permit,
151     * </ul>
152     * then {@link InterruptedException} is thrown and the current thread's
153     * interrupted status is cleared.
154     *
155     * @throws InterruptedException if the current thread is interrupted
156     *
157     * @see Thread#interrupt
158     */
159 dl 1.2 public void acquire() throws InterruptedException {
160     lock.lockInterruptibly();
161     try {
162 dl 1.4 while (count <= 0)
163     available.await();
164 dl 1.2 --count;
165 tim 1.8 } catch (InterruptedException ie) {
166 dl 1.2 available.signal();
167     throw ie;
168 tim 1.8 } finally {
169 dl 1.2 lock.unlock();
170     }
171     }
172 tim 1.1
173     /**
174     * Acquires a permit from this semaphore, blocking until one is
175     * available.
176     *
177     * <p>Acquires a permit, if one is available and returns immediately,
178     * reducing the number of available permits by one.
179     * <p>If no permit is available then the current thread becomes
180     * disabled for thread scheduling purposes and lies dormant until
181     * some other thread invokes the {@link #release} method for this
182     * semaphore and the current thread happens to be chosen as the
183     * thread to receive the permit.
184     *
185     * <p>If the current thread
186     * is {@link Thread#interrupt interrupted} while waiting
187     * for a permit then it will continue to wait, but the time at which
188     * the thread is assigned a permit may change compared to the time it
189     * would have received the permit had no interruption occurred. When the
190     * thread does return from this method its interrupt status will be set.
191     *
192     */
193 dl 1.2 public void acquireUninterruptibly() {
194     lock.lock();
195     try {
196 dl 1.4 while (count <= 0)
197     available.awaitUninterruptibly();
198 dl 1.2 --count;
199 tim 1.8 } finally {
200 dl 1.2 lock.unlock();
201     }
202     }
203 tim 1.1
204     /**
205     * Acquires a permit from this semaphore, only if one is available at the
206     * time of invocation.
207     * <p>Acquires a permit, if one is available and returns immediately,
208     * with the value <tt>true</tt>,
209     * reducing the number of available permits by one.
210     *
211     * <p>If no permit is available then this method will return
212     * immediately with the value <tt>false</tt>.
213     *
214     * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
215     * otherwise.
216     */
217     public boolean tryAcquire() {
218 dl 1.2 lock.lock();
219     try {
220     if (count > 0) {
221     --count;
222     return true;
223     }
224     return false;
225 tim 1.8 } finally {
226 dl 1.2 lock.unlock();
227     }
228 tim 1.1 }
229    
230     /**
231     * Acquires a permit from this semaphore, if one becomes available
232     * within the given waiting time and the
233     * current thread has not been {@link Thread#interrupt interrupted}.
234     * <p>Acquires a permit, if one is available and returns immediately,
235     * with the value <tt>true</tt>,
236     * reducing the number of available permits by one.
237     * <p>If no permit is available then
238     * the current thread becomes disabled for thread scheduling
239     * purposes and lies dormant until one of three things happens:
240     * <ul>
241     * <li>Some other thread invokes the {@link #release} method for this
242     * semaphore and the current thread happens to be chosen as the
243     * thread to receive the permit; or
244     * <li>Some other thread {@link Thread#interrupt interrupts} the current
245     * thread; or
246     * <li>The specified waiting time elapses.
247     * </ul>
248     * <p>If a permit is acquired then the value <tt>true</tt> is returned.
249     * <p>If the current thread:
250     * <ul>
251     * <li>has its interrupted status set on entry to this method; or
252     * <li>is {@link Thread#interrupt interrupted} while waiting to acquire
253     * a permit,
254     * </ul>
255     * then {@link InterruptedException} is thrown and the current thread's
256     * interrupted status is cleared.
257     * <p>If the specified waiting time elapses then the value <tt>false</tt>
258     * is returned.
259 dholmes 1.10 * If the time is
260 tim 1.1 * less than or equal to zero, the method will not wait at all.
261     *
262     * @param timeout the maximum time to wait for a permit
263 dl 1.13 * @param unit the time unit of the <tt>timeout</tt> argument.
264 tim 1.1 * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
265     * if the waiting time elapsed before a permit was acquired.
266     *
267     * @throws InterruptedException if the current thread is interrupted
268     *
269     * @see Thread#interrupt
270     *
271     */
272 dl 1.13 public boolean tryAcquire(long timeout, TimeUnit unit)
273 tim 1.1 throws InterruptedException {
274 dl 1.2 lock.lockInterruptibly();
275 dl 1.13 long nanos = unit.toNanos(timeout);
276 dl 1.2 try {
277     for (;;) {
278     if (count > 0) {
279     --count;
280     return true;
281     }
282     if (nanos <= 0)
283     return false;
284     nanos = available.awaitNanos(nanos);
285     }
286 tim 1.8 } catch (InterruptedException ie) {
287 dl 1.2 available.signal();
288     throw ie;
289 tim 1.8 } finally {
290 dl 1.2 lock.unlock();
291     }
292 tim 1.1 }
293    
294     /**
295     * Releases a permit, returning it to the semaphore.
296     * <p>Releases a permit, increasing the number of available permits
297     * by one.
298     * If any threads are blocking trying to acquire a permit, then one
299     * is selected and given the permit that was just released.
300     * That thread is re-enabled for thread scheduling purposes.
301     * <p>There is no requirement that a thread that releases a permit must
302     * have acquired that permit by calling {@link #acquire}.
303     * Correct usage of a semaphore is established by programming convention
304     * in the application.
305     */
306 dl 1.2 public void release() {
307 dl 1.7 lock.lock();
308 dl 1.2 try {
309     ++count;
310     available.signal();
311 tim 1.8 } finally {
312 dl 1.2 lock.unlock();
313     }
314     }
315    
316 tim 1.1
317     /**
318     * Return the current number of permits available in this semaphore.
319     * <p>This method is typically used for debugging and testing purposes.
320     * @return the number of permits available in this semaphore.
321     */
322     public long availablePermits() {
323 dl 1.2 lock.lock();
324     try {
325     return count;
326 tim 1.8 } finally {
327 dl 1.2 lock.unlock();
328     }
329 tim 1.1 }
330     }
331    
332    
333