118 |
|
* |
119 |
|
*/ |
120 |
|
|
121 |
< |
public class Semaphore extends AbstractQueuedSynchronizer implements java.io.Serializable { |
121 |
> |
public class Semaphore implements java.io.Serializable { |
122 |
|
private static final long serialVersionUID = -3222578661600680210L; |
123 |
< |
private final boolean fair; |
123 |
> |
/** Sync mechanics via AbstractQueuedSynchronizer subclass */ |
124 |
> |
private final Sync sync; |
125 |
> |
|
126 |
> |
|
127 |
> |
private final static class Sync extends AbstractQueuedSynchronizer { |
128 |
> |
final boolean fair; |
129 |
> |
Sync(int permits, boolean fair) { |
130 |
> |
this.fair = fair; |
131 |
> |
getState().set(permits); |
132 |
> |
} |
133 |
> |
|
134 |
> |
public final int acquireSharedState(boolean isQueued, int acquires, |
135 |
> |
Thread current) { |
136 |
> |
final AtomicInteger perms = getState(); |
137 |
> |
if (!isQueued && fair && hasWaiters()) |
138 |
> |
return -1; |
139 |
> |
for (;;) { |
140 |
> |
int available = perms.get(); |
141 |
> |
int remaining = available - acquires; |
142 |
> |
if (remaining < 0 || |
143 |
> |
perms.compareAndSet(available, remaining)) |
144 |
> |
return remaining; |
145 |
> |
} |
146 |
> |
} |
147 |
> |
|
148 |
> |
public final boolean releaseSharedState(int releases) { |
149 |
> |
final AtomicInteger perms = getState(); |
150 |
> |
for (;;) { |
151 |
> |
int p = perms.get(); |
152 |
> |
if (perms.compareAndSet(p, p + releases)) |
153 |
> |
return true; |
154 |
> |
} |
155 |
> |
} |
156 |
> |
|
157 |
> |
public final int acquireExclusiveState(boolean isQueued, |
158 |
> |
int acquires, |
159 |
> |
Thread current) { |
160 |
> |
throw new UnsupportedOperationException(); |
161 |
> |
} |
162 |
> |
|
163 |
> |
public final boolean releaseExclusiveState(int releases) { |
164 |
> |
throw new UnsupportedOperationException(); |
165 |
> |
} |
166 |
> |
|
167 |
> |
public final void checkConditionAccess(Thread thread, boolean waiting) { |
168 |
> |
throw new UnsupportedOperationException(); |
169 |
> |
} |
170 |
> |
|
171 |
> |
} |
172 |
|
|
173 |
|
/** |
174 |
|
* Construct a <tt>Semaphore</tt> with the given number of |
180 |
|
* first-out granting of permits under contention, else false. |
181 |
|
*/ |
182 |
|
public Semaphore(int permits, boolean fair) { |
183 |
< |
this.fair = fair; |
136 |
< |
getState().set(permits); |
183 |
> |
sync = new Sync(permits, fair); |
184 |
|
} |
185 |
|
|
186 |
|
/** |
213 |
|
* @see Thread#interrupt |
214 |
|
*/ |
215 |
|
public void acquire() throws InterruptedException { |
216 |
< |
acquireSharedInterruptibly(1); |
216 |
> |
sync.acquireSharedInterruptibly(1); |
217 |
|
} |
218 |
|
|
219 |
|
/** |
236 |
|
* |
237 |
|
*/ |
238 |
|
public void acquireUninterruptibly() { |
239 |
< |
acquireSharedUninterruptibly(1); |
239 |
> |
sync.acquireSharedUninterruptibly(1); |
240 |
|
} |
241 |
|
|
242 |
|
/** |
253 |
|
* otherwise. |
254 |
|
*/ |
255 |
|
public boolean tryAcquire() { |
256 |
< |
return acquireSharedState(false, 1, null) >= 0; |
256 |
> |
return sync.acquireSharedState(false, 1, null) >= 0; |
257 |
|
} |
258 |
|
|
259 |
|
/** |
299 |
|
*/ |
300 |
|
public boolean tryAcquire(long timeout, TimeUnit unit) |
301 |
|
throws InterruptedException { |
302 |
< |
return acquireSharedTimed(1, unit.toNanos(timeout)); |
302 |
> |
return sync.acquireSharedTimed(1, unit.toNanos(timeout)); |
303 |
|
} |
304 |
|
|
305 |
|
/** |
315 |
|
* in the application. |
316 |
|
*/ |
317 |
|
public void release() { |
318 |
< |
releaseShared(1); |
318 |
> |
sync.releaseShared(1); |
319 |
|
} |
320 |
|
|
321 |
|
/** |
359 |
|
*/ |
360 |
|
public void acquire(int permits) throws InterruptedException { |
361 |
|
if (permits < 0) throw new IllegalArgumentException(); |
362 |
< |
acquireSharedInterruptibly(permits); |
362 |
> |
sync.acquireSharedInterruptibly(permits); |
363 |
|
} |
364 |
|
|
365 |
|
/** |
388 |
|
*/ |
389 |
|
public void acquireUninterruptibly(int permits) { |
390 |
|
if (permits < 0) throw new IllegalArgumentException(); |
391 |
< |
acquireSharedUninterruptibly(permits); |
391 |
> |
sync.acquireSharedUninterruptibly(permits); |
392 |
|
} |
393 |
|
|
394 |
|
/** |
410 |
|
*/ |
411 |
|
public boolean tryAcquire(int permits) { |
412 |
|
if (permits < 0) throw new IllegalArgumentException(); |
413 |
< |
return acquireSharedState(false, permits, null) >= 0; |
413 |
> |
return sync.acquireSharedState(false, permits, null) >= 0; |
414 |
|
} |
415 |
|
|
416 |
|
/** |
467 |
|
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) |
468 |
|
throws InterruptedException { |
469 |
|
if (permits < 0) throw new IllegalArgumentException(); |
470 |
< |
return acquireSharedTimed(permits, unit.toNanos(timeout)); |
470 |
> |
return sync.acquireSharedTimed(permits, unit.toNanos(timeout)); |
471 |
|
} |
472 |
|
|
473 |
|
|
497 |
|
*/ |
498 |
|
public void release(int permits) { |
499 |
|
if (permits < 0) throw new IllegalArgumentException(); |
500 |
< |
releaseShared(permits); |
500 |
> |
sync.releaseShared(permits); |
501 |
|
} |
502 |
|
|
503 |
|
/** |
506 |
|
* @return the number of permits available in this semaphore. |
507 |
|
*/ |
508 |
|
public int availablePermits() { |
509 |
< |
return getState().get(); |
509 |
> |
return sync.getState().get(); |
510 |
|
} |
511 |
|
|
512 |
|
/** |
521 |
|
*/ |
522 |
|
protected void reducePermits(int reduction) { |
523 |
|
if (reduction < 0) throw new IllegalArgumentException(); |
524 |
< |
getState().getAndAdd(-reduction); |
524 |
> |
sync.getState().getAndAdd(-reduction); |
525 |
|
} |
526 |
|
|
527 |
|
/** |
529 |
|
* @return true if this semaphore has fairness set true. |
530 |
|
*/ |
531 |
|
public boolean isFair() { |
532 |
< |
return fair; |
532 |
> |
return sync.fair; |
533 |
|
} |
534 |
|
|
488 |
– |
// Implement abstract methods |
535 |
|
|
536 |
|
/** |
537 |
< |
* Sets internal state to indicate permits acquired if available |
538 |
< |
*/ |
539 |
< |
protected final int acquireSharedState(boolean isQueued, int acquires, |
540 |
< |
Thread current) { |
541 |
< |
final AtomicInteger perms = getState(); |
542 |
< |
if (!isQueued && fair && hasWaiters()) |
543 |
< |
return -1; |
544 |
< |
for (;;) { |
499 |
< |
int available = perms.get(); |
500 |
< |
int remaining = available - acquires; |
501 |
< |
if (remaining < 0 || |
502 |
< |
perms.compareAndSet(available, remaining)) |
503 |
< |
return remaining; |
504 |
< |
} |
505 |
< |
} |
506 |
< |
|
507 |
< |
/** |
508 |
< |
* Sets internal state to indicate permits have been released |
537 |
> |
* Queries whether any threads are waiting to acquire. Note that |
538 |
> |
* because cancellations may occur at any time, a <tt>true</tt> |
539 |
> |
* return does not guarantee that any other thread will ever |
540 |
> |
* acquire. This method is designed primarily for use in |
541 |
> |
* monitoring of the system state. |
542 |
> |
* |
543 |
> |
* @return true if there may be other threads waiting to acquire |
544 |
> |
* the lock. |
545 |
|
*/ |
546 |
< |
protected final boolean releaseSharedState(int releases) { |
547 |
< |
final AtomicInteger perms = getState(); |
512 |
< |
for (;;) { |
513 |
< |
int p = perms.get(); |
514 |
< |
if (perms.compareAndSet(p, p + releases)) |
515 |
< |
return true; |
516 |
< |
} |
546 |
> |
public final boolean hasWaiters() { |
547 |
> |
return sync.hasWaiters(); |
548 |
|
} |
549 |
|
|
519 |
– |
/** |
520 |
– |
* Always throws UnsupportedOperationException |
521 |
– |
*/ |
522 |
– |
protected final int acquireExclusiveState(boolean isQueued, int acquires, |
523 |
– |
Thread current) { |
524 |
– |
throw new UnsupportedOperationException(); |
525 |
– |
} |
550 |
|
|
551 |
|
/** |
552 |
< |
* Always throws UnsupportedOperationException |
552 |
> |
* Returns an estimate of the number of threads waiting to |
553 |
> |
* acquire. The value is only an estimate because the number of |
554 |
> |
* threads may change dynamically while this method traverses |
555 |
> |
* internal data structures. This method is designed for use in |
556 |
> |
* monitoring of the system state, not for synchronization |
557 |
> |
* control. |
558 |
> |
* @return the estimated number of threads waiting for this lock |
559 |
|
*/ |
560 |
< |
protected final boolean releaseExclusiveState(int releases) { |
561 |
< |
throw new UnsupportedOperationException(); |
560 |
> |
public final int getQueueLength() { |
561 |
> |
return sync.getQueueLength(); |
562 |
|
} |
563 |
|
|
564 |
|
/** |
565 |
< |
* Always throws UnsupportedOperationException |
565 |
> |
* Returns a collection containing threads that may be waiting to |
566 |
> |
* acquire. Because the actual set of threads may change |
567 |
> |
* dynamically while constructing this result, the returned |
568 |
> |
* collection is only a best-effort estimate. The elements of the |
569 |
> |
* returned collection are in no particular order. This method is |
570 |
> |
* designed to facilitate construction of subclasses that provide |
571 |
> |
* more extensive monitoring facilities. |
572 |
> |
* @return the collection of threads |
573 |
|
*/ |
574 |
< |
protected final void checkConditionAccess(Thread thread, boolean waiting) { |
575 |
< |
throw new UnsupportedOperationException(); |
574 |
> |
protected Collection<Thread> getQueuedThreads() { |
575 |
> |
return sync.getQueuedThreads(); |
576 |
|
} |
577 |
< |
|
577 |
> |
|
578 |
|
} |