1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 */ 6 7 package java.util.concurrent; 8 import java.util.Collection; 9 import java.util.concurrent.locks.AbstractQueuedSynchronizer; 10 11 /** 12 * A counting semaphore. Conceptually, a semaphore maintains a set of 13 * permits. Each {@link #acquire} blocks if necessary until a permit is 14 * available, and then takes it. Each {@link #release} adds a permit, 15 * potentially releasing a blocking acquirer. 16 * However, no actual permit objects are used; the {@code Semaphore} just 17 * keeps a count of the number available and acts accordingly. 18 * 19 * <p>Semaphores are often used to restrict the number of threads than can 20 * access some (physical or logical) resource. For example, here is 21 * a class that uses a semaphore to control access to a pool of items: 22 * <pre> {@code 23 * class Pool { 24 * private static final int MAX_AVAILABLE = 100; 25 * private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); 26 * 27 * public Object getItem() throws InterruptedException { 28 * available.acquire(); 29 * return getNextAvailableItem(); 30 * } 31 * 32 * public void putItem(Object x) { 33 * if (markAsUnused(x)) 34 * available.release(); 35 * } 36 * 37 * // Not a particularly efficient data structure; just for demo 38 * 39 * protected Object[] items = ... whatever kinds of items being managed 40 * protected boolean[] used = new boolean[MAX_AVAILABLE]; 41 * 42 * protected synchronized Object getNextAvailableItem() { 43 * for (int i = 0; i < MAX_AVAILABLE; ++i) { 44 * if (!used[i]) { 45 * used[i] = true; 46 * return items[i]; 47 * } 48 * } 49 * return null; // not reached 50 * } 51 * 52 * protected synchronized boolean markAsUnused(Object item) { 53 * for (int i = 0; i < MAX_AVAILABLE; ++i) { 54 * if (item == items[i]) { 55 * if (used[i]) { 56 * used[i] = false; 57 * return true; 58 * } else 59 * return false; 60 * } 61 * } 62 * return false; 63 * } 64 * }}</pre> 65 * 66 * <p>Before obtaining an item each thread must acquire a permit from 67 * the semaphore, guaranteeing that an item is available for use. When 68 * the thread has finished with the item it is returned back to the 69 * pool and a permit is returned to the semaphore, allowing another 70 * thread to acquire that item. Note that no synchronization lock is 71 * held when {@link #acquire} is called as that would prevent an item 72 * from being returned to the pool. The semaphore encapsulates the 73 * synchronization needed to restrict access to the pool, separately 74 * from any synchronization needed to maintain the consistency of the 75 * pool itself. 76 * 77 * <p>A semaphore initialized to one, and which is used such that it 78 * only has at most one permit available, can serve as a mutual 79 * exclusion lock. This is more commonly known as a <em>binary 80 * semaphore</em>, because it only has two states: one permit 81 * available, or zero permits available. When used in this way, the 82 * binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock} 83 * implementations), that the "lock" can be released by a 84 * thread other than the owner (as semaphores have no notion of 85 * ownership). This can be useful in some specialized contexts, such 86 * as deadlock recovery. 87 * 88 * <p>The constructor for this class optionally accepts a 89 * <em>fairness</em> parameter. When set false, this class makes no 90 * guarantees about the order in which threads acquire permits. In 91 * particular, <em>barging</em> is permitted, that is, a thread 92 * invoking {@link #acquire} can be allocated a permit ahead of a 93 * thread that has been waiting - logically the new thread places itself at 94 * the head of the queue of waiting threads. When fairness is set true, the 95 * semaphore guarantees that threads invoking any of the {@link 96 * #acquire() acquire} methods are selected to obtain permits in the order in 97 * which their invocation of those methods was processed 98 * (first-in-first-out; FIFO). Note that FIFO ordering necessarily 99 * applies to specific internal points of execution within these 100 * methods. So, it is possible for one thread to invoke 101 * {@code acquire} before another, but reach the ordering point after 102 * the other, and similarly upon return from the method. 103 * Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not 104 * honor the fairness setting, but will take any permits that are 105 * available. 106 * 107 * <p>Generally, semaphores used to control resource access should be 108 * initialized as fair, to ensure that no thread is starved out from 109 * accessing a resource. When using semaphores for other kinds of 110 * synchronization control, the throughput advantages of non-fair 111 * ordering often outweigh fairness considerations. 112 * 113 * <p>This class also provides convenience methods to {@link 114 * #acquire(int) acquire} and {@link #release(int) release} multiple 115 * permits at a time. Beware of the increased risk of indefinite 116 * postponement when these methods are used without fairness set true. 117 * 118 * <p>Memory consistency effects: Actions in a thread prior to calling 119 * a "release" method such as {@code release()} 120 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> 121 * actions following a successful "acquire" method such as {@code acquire()} 122 * in another thread. 123 * 124 * @since 1.5 125 * @author Doug Lea 126 */ 127 public class Semaphore implements java.io.Serializable { 128 private static final long serialVersionUID = -3222578661600680210L; 129 /** All mechanics via AbstractQueuedSynchronizer subclass */ 130 private final Sync sync; 131 132 /** 133 * Synchronization implementation for semaphore. Uses AQS state 134 * to represent permits. Subclassed into fair and nonfair 135 * versions. 136 */ 137 abstract static class Sync extends AbstractQueuedSynchronizer { 138 private static final long serialVersionUID = 1192457210091910933L; 139 Sync(int permits)140 Sync(int permits) { 141 setState(permits); 142 } 143 getPermits()144 final int getPermits() { 145 return getState(); 146 } 147 nonfairTryAcquireShared(int acquires)148 final int nonfairTryAcquireShared(int acquires) { 149 for (;;) { 150 int available = getState(); 151 int remaining = available - acquires; 152 if (remaining < 0 || 153 compareAndSetState(available, remaining)) 154 return remaining; 155 } 156 } 157 tryReleaseShared(int releases)158 protected final boolean tryReleaseShared(int releases) { 159 for (;;) { 160 int current = getState(); 161 int next = current + releases; 162 if (next < current) // overflow 163 throw new Error("Maximum permit count exceeded"); 164 if (compareAndSetState(current, next)) 165 return true; 166 } 167 } 168 reducePermits(int reductions)169 final void reducePermits(int reductions) { 170 for (;;) { 171 int current = getState(); 172 int next = current - reductions; 173 if (next > current) // underflow 174 throw new Error("Permit count underflow"); 175 if (compareAndSetState(current, next)) 176 return; 177 } 178 } 179 drainPermits()180 final int drainPermits() { 181 for (;;) { 182 int current = getState(); 183 if (current == 0 || compareAndSetState(current, 0)) 184 return current; 185 } 186 } 187 } 188 189 /** 190 * NonFair version 191 */ 192 static final class NonfairSync extends Sync { 193 private static final long serialVersionUID = -2694183684443567898L; 194 NonfairSync(int permits)195 NonfairSync(int permits) { 196 super(permits); 197 } 198 tryAcquireShared(int acquires)199 protected int tryAcquireShared(int acquires) { 200 return nonfairTryAcquireShared(acquires); 201 } 202 } 203 204 /** 205 * Fair version 206 */ 207 static final class FairSync extends Sync { 208 private static final long serialVersionUID = 2014338818796000944L; 209 FairSync(int permits)210 FairSync(int permits) { 211 super(permits); 212 } 213 tryAcquireShared(int acquires)214 protected int tryAcquireShared(int acquires) { 215 for (;;) { 216 if (hasQueuedPredecessors()) 217 return -1; 218 int available = getState(); 219 int remaining = available - acquires; 220 if (remaining < 0 || 221 compareAndSetState(available, remaining)) 222 return remaining; 223 } 224 } 225 } 226 227 /** 228 * Creates a {@code Semaphore} with the given number of 229 * permits and nonfair fairness setting. 230 * 231 * @param permits the initial number of permits available. 232 * This value may be negative, in which case releases 233 * must occur before any acquires will be granted. 234 */ Semaphore(int permits)235 public Semaphore(int permits) { 236 sync = new NonfairSync(permits); 237 } 238 239 /** 240 * Creates a {@code Semaphore} with the given number of 241 * permits and the given fairness setting. 242 * 243 * @param permits the initial number of permits available. 244 * This value may be negative, in which case releases 245 * must occur before any acquires will be granted. 246 * @param fair {@code true} if this semaphore will guarantee 247 * first-in first-out granting of permits under contention, 248 * else {@code false} 249 */ Semaphore(int permits, boolean fair)250 public Semaphore(int permits, boolean fair) { 251 sync = fair ? new FairSync(permits) : new NonfairSync(permits); 252 } 253 254 /** 255 * Acquires a permit from this semaphore, blocking until one is 256 * available, or the thread is {@linkplain Thread#interrupt interrupted}. 257 * 258 * <p>Acquires a permit, if one is available and returns immediately, 259 * reducing the number of available permits by one. 260 * 261 * <p>If no permit is available then the current thread becomes 262 * disabled for thread scheduling purposes and lies dormant until 263 * one of two things happens: 264 * <ul> 265 * <li>Some other thread invokes the {@link #release} method for this 266 * semaphore and the current thread is next to be assigned a permit; or 267 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 268 * the current thread. 269 * </ul> 270 * 271 * <p>If the current thread: 272 * <ul> 273 * <li>has its interrupted status set on entry to this method; or 274 * <li>is {@linkplain Thread#interrupt interrupted} while waiting 275 * for a permit, 276 * </ul> 277 * then {@link InterruptedException} is thrown and the current thread's 278 * interrupted status is cleared. 279 * 280 * @throws InterruptedException if the current thread is interrupted 281 */ acquire()282 public void acquire() throws InterruptedException { 283 sync.acquireSharedInterruptibly(1); 284 } 285 286 /** 287 * Acquires a permit from this semaphore, blocking until one is 288 * available. 289 * 290 * <p>Acquires a permit, if one is available and returns immediately, 291 * reducing the number of available permits by one. 292 * 293 * <p>If no permit is available then the current thread becomes 294 * disabled for thread scheduling purposes and lies dormant until 295 * some other thread invokes the {@link #release} method for this 296 * semaphore and the current thread is next to be assigned a permit. 297 * 298 * <p>If the current thread is {@linkplain Thread#interrupt interrupted} 299 * while waiting for a permit then it will continue to wait, but the 300 * time at which the thread is assigned a permit may change compared to 301 * the time it would have received the permit had no interruption 302 * occurred. When the thread does return from this method its interrupt 303 * status will be set. 304 */ acquireUninterruptibly()305 public void acquireUninterruptibly() { 306 sync.acquireShared(1); 307 } 308 309 /** 310 * Acquires a permit from this semaphore, only if one is available at the 311 * time of invocation. 312 * 313 * <p>Acquires a permit, if one is available and returns immediately, 314 * with the value {@code true}, 315 * reducing the number of available permits by one. 316 * 317 * <p>If no permit is available then this method will return 318 * immediately with the value {@code false}. 319 * 320 * <p>Even when this semaphore has been set to use a 321 * fair ordering policy, a call to {@code tryAcquire()} <em>will</em> 322 * immediately acquire a permit if one is available, whether or not 323 * other threads are currently waiting. 324 * This "barging" behavior can be useful in certain 325 * circumstances, even though it breaks fairness. If you want to honor 326 * the fairness setting, then use 327 * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) } 328 * which is almost equivalent (it also detects interruption). 329 * 330 * @return {@code true} if a permit was acquired and {@code false} 331 * otherwise 332 */ tryAcquire()333 public boolean tryAcquire() { 334 return sync.nonfairTryAcquireShared(1) >= 0; 335 } 336 337 /** 338 * Acquires a permit from this semaphore, if one becomes available 339 * within the given waiting time and the current thread has not 340 * been {@linkplain Thread#interrupt interrupted}. 341 * 342 * <p>Acquires a permit, if one is available and returns immediately, 343 * with the value {@code true}, 344 * reducing the number of available permits by one. 345 * 346 * <p>If no permit is available then the current thread becomes 347 * disabled for thread scheduling purposes and lies dormant until 348 * one of three things happens: 349 * <ul> 350 * <li>Some other thread invokes the {@link #release} method for this 351 * semaphore and the current thread is next to be assigned a permit; or 352 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 353 * the current thread; or 354 * <li>The specified waiting time elapses. 355 * </ul> 356 * 357 * <p>If a permit is acquired then the value {@code true} is returned. 358 * 359 * <p>If the current thread: 360 * <ul> 361 * <li>has its interrupted status set on entry to this method; or 362 * <li>is {@linkplain Thread#interrupt interrupted} while waiting 363 * to acquire a permit, 364 * </ul> 365 * then {@link InterruptedException} is thrown and the current thread's 366 * interrupted status is cleared. 367 * 368 * <p>If the specified waiting time elapses then the value {@code false} 369 * is returned. If the time is less than or equal to zero, the method 370 * will not wait at all. 371 * 372 * @param timeout the maximum time to wait for a permit 373 * @param unit the time unit of the {@code timeout} argument 374 * @return {@code true} if a permit was acquired and {@code false} 375 * if the waiting time elapsed before a permit was acquired 376 * @throws InterruptedException if the current thread is interrupted 377 */ tryAcquire(long timeout, TimeUnit unit)378 public boolean tryAcquire(long timeout, TimeUnit unit) 379 throws InterruptedException { 380 return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); 381 } 382 383 /** 384 * Releases a permit, returning it to the semaphore. 385 * 386 * <p>Releases a permit, increasing the number of available permits by 387 * one. If any threads are trying to acquire a permit, then one is 388 * selected and given the permit that was just released. That thread 389 * is (re)enabled for thread scheduling purposes. 390 * 391 * <p>There is no requirement that a thread that releases a permit must 392 * have acquired that permit by calling {@link #acquire}. 393 * Correct usage of a semaphore is established by programming convention 394 * in the application. 395 */ release()396 public void release() { 397 sync.releaseShared(1); 398 } 399 400 /** 401 * Acquires the given number of permits from this semaphore, 402 * blocking until all are available, 403 * or the thread is {@linkplain Thread#interrupt interrupted}. 404 * 405 * <p>Acquires the given number of permits, if they are available, 406 * and returns immediately, reducing the number of available permits 407 * by the given amount. 408 * 409 * <p>If insufficient permits are available then the current thread becomes 410 * disabled for thread scheduling purposes and lies dormant until 411 * one of two things happens: 412 * <ul> 413 * <li>Some other thread invokes one of the {@link #release() release} 414 * methods for this semaphore, the current thread is next to be assigned 415 * permits and the number of available permits satisfies this request; or 416 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 417 * the current thread. 418 * </ul> 419 * 420 * <p>If the current thread: 421 * <ul> 422 * <li>has its interrupted status set on entry to this method; or 423 * <li>is {@linkplain Thread#interrupt interrupted} while waiting 424 * for a permit, 425 * </ul> 426 * then {@link InterruptedException} is thrown and the current thread's 427 * interrupted status is cleared. 428 * Any permits that were to be assigned to this thread are instead 429 * assigned to other threads trying to acquire permits, as if 430 * permits had been made available by a call to {@link #release()}. 431 * 432 * @param permits the number of permits to acquire 433 * @throws InterruptedException if the current thread is interrupted 434 * @throws IllegalArgumentException if {@code permits} is negative 435 */ acquire(int permits)436 public void acquire(int permits) throws InterruptedException { 437 if (permits < 0) throw new IllegalArgumentException(); 438 sync.acquireSharedInterruptibly(permits); 439 } 440 441 /** 442 * Acquires the given number of permits from this semaphore, 443 * blocking until all are available. 444 * 445 * <p>Acquires the given number of permits, if they are available, 446 * and returns immediately, reducing the number of available permits 447 * by the given amount. 448 * 449 * <p>If insufficient permits are available then the current thread becomes 450 * disabled for thread scheduling purposes and lies dormant until 451 * some other thread invokes one of the {@link #release() release} 452 * methods for this semaphore, the current thread is next to be assigned 453 * permits and the number of available permits satisfies this request. 454 * 455 * <p>If the current thread is {@linkplain Thread#interrupt interrupted} 456 * while waiting for permits then it will continue to wait and its 457 * position in the queue is not affected. When the thread does return 458 * from this method its interrupt status will be set. 459 * 460 * @param permits the number of permits to acquire 461 * @throws IllegalArgumentException if {@code permits} is negative 462 */ acquireUninterruptibly(int permits)463 public void acquireUninterruptibly(int permits) { 464 if (permits < 0) throw new IllegalArgumentException(); 465 sync.acquireShared(permits); 466 } 467 468 /** 469 * Acquires the given number of permits from this semaphore, only 470 * if all are available at the time of invocation. 471 * 472 * <p>Acquires the given number of permits, if they are available, and 473 * returns immediately, with the value {@code true}, 474 * reducing the number of available permits by the given amount. 475 * 476 * <p>If insufficient permits are available then this method will return 477 * immediately with the value {@code false} and the number of available 478 * permits is unchanged. 479 * 480 * <p>Even when this semaphore has been set to use a fair ordering 481 * policy, a call to {@code tryAcquire} <em>will</em> 482 * immediately acquire a permit if one is available, whether or 483 * not other threads are currently waiting. This 484 * "barging" behavior can be useful in certain 485 * circumstances, even though it breaks fairness. If you want to 486 * honor the fairness setting, then use {@link #tryAcquire(int, 487 * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) } 488 * which is almost equivalent (it also detects interruption). 489 * 490 * @param permits the number of permits to acquire 491 * @return {@code true} if the permits were acquired and 492 * {@code false} otherwise 493 * @throws IllegalArgumentException if {@code permits} is negative 494 */ tryAcquire(int permits)495 public boolean tryAcquire(int permits) { 496 if (permits < 0) throw new IllegalArgumentException(); 497 return sync.nonfairTryAcquireShared(permits) >= 0; 498 } 499 500 /** 501 * Acquires the given number of permits from this semaphore, if all 502 * become available within the given waiting time and the current 503 * thread has not been {@linkplain Thread#interrupt interrupted}. 504 * 505 * <p>Acquires the given number of permits, if they are available and 506 * returns immediately, with the value {@code true}, 507 * reducing the number of available permits by the given amount. 508 * 509 * <p>If insufficient permits are available then 510 * the current thread becomes disabled for thread scheduling 511 * purposes and lies dormant until one of three things happens: 512 * <ul> 513 * <li>Some other thread invokes one of the {@link #release() release} 514 * methods for this semaphore, the current thread is next to be assigned 515 * permits and the number of available permits satisfies this request; or 516 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 517 * the current thread; or 518 * <li>The specified waiting time elapses. 519 * </ul> 520 * 521 * <p>If the permits are acquired then the value {@code true} is returned. 522 * 523 * <p>If the current thread: 524 * <ul> 525 * <li>has its interrupted status set on entry to this method; or 526 * <li>is {@linkplain Thread#interrupt interrupted} while waiting 527 * to acquire the permits, 528 * </ul> 529 * then {@link InterruptedException} is thrown and the current thread's 530 * interrupted status is cleared. 531 * Any permits that were to be assigned to this thread, are instead 532 * assigned to other threads trying to acquire permits, as if 533 * the permits had been made available by a call to {@link #release()}. 534 * 535 * <p>If the specified waiting time elapses then the value {@code false} 536 * is returned. If the time is less than or equal to zero, the method 537 * will not wait at all. Any permits that were to be assigned to this 538 * thread, are instead assigned to other threads trying to acquire 539 * permits, as if the permits had been made available by a call to 540 * {@link #release()}. 541 * 542 * @param permits the number of permits to acquire 543 * @param timeout the maximum time to wait for the permits 544 * @param unit the time unit of the {@code timeout} argument 545 * @return {@code true} if all permits were acquired and {@code false} 546 * if the waiting time elapsed before all permits were acquired 547 * @throws InterruptedException if the current thread is interrupted 548 * @throws IllegalArgumentException if {@code permits} is negative 549 */ tryAcquire(int permits, long timeout, TimeUnit unit)550 public boolean tryAcquire(int permits, long timeout, TimeUnit unit) 551 throws InterruptedException { 552 if (permits < 0) throw new IllegalArgumentException(); 553 return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout)); 554 } 555 556 /** 557 * Releases the given number of permits, returning them to the semaphore. 558 * 559 * <p>Releases the given number of permits, increasing the number of 560 * available permits by that amount. 561 * If any threads are trying to acquire permits, then one 562 * is selected and given the permits that were just released. 563 * If the number of available permits satisfies that thread's request 564 * then that thread is (re)enabled for thread scheduling purposes; 565 * otherwise the thread will wait until sufficient permits are available. 566 * If there are still permits available 567 * after this thread's request has been satisfied, then those permits 568 * are assigned in turn to other threads trying to acquire permits. 569 * 570 * <p>There is no requirement that a thread that releases a permit must 571 * have acquired that permit by calling {@link Semaphore#acquire acquire}. 572 * Correct usage of a semaphore is established by programming convention 573 * in the application. 574 * 575 * @param permits the number of permits to release 576 * @throws IllegalArgumentException if {@code permits} is negative 577 */ release(int permits)578 public void release(int permits) { 579 if (permits < 0) throw new IllegalArgumentException(); 580 sync.releaseShared(permits); 581 } 582 583 /** 584 * Returns the current number of permits available in this semaphore. 585 * 586 * <p>This method is typically used for debugging and testing purposes. 587 * 588 * @return the number of permits available in this semaphore 589 */ availablePermits()590 public int availablePermits() { 591 return sync.getPermits(); 592 } 593 594 /** 595 * Acquires and returns all permits that are immediately available. 596 * 597 * @return the number of permits acquired 598 */ drainPermits()599 public int drainPermits() { 600 return sync.drainPermits(); 601 } 602 603 /** 604 * Shrinks the number of available permits by the indicated 605 * reduction. This method can be useful in subclasses that use 606 * semaphores to track resources that become unavailable. This 607 * method differs from {@code acquire} in that it does not block 608 * waiting for permits to become available. 609 * 610 * @param reduction the number of permits to remove 611 * @throws IllegalArgumentException if {@code reduction} is negative 612 */ reducePermits(int reduction)613 protected void reducePermits(int reduction) { 614 if (reduction < 0) throw new IllegalArgumentException(); 615 sync.reducePermits(reduction); 616 } 617 618 /** 619 * Returns {@code true} if this semaphore has fairness set true. 620 * 621 * @return {@code true} if this semaphore has fairness set true 622 */ isFair()623 public boolean isFair() { 624 return sync instanceof FairSync; 625 } 626 627 /** 628 * Queries whether any threads are waiting to acquire. Note that 629 * because cancellations may occur at any time, a {@code true} 630 * return does not guarantee that any other thread will ever 631 * acquire. This method is designed primarily for use in 632 * monitoring of the system state. 633 * 634 * @return {@code true} if there may be other threads waiting to 635 * acquire the lock 636 */ hasQueuedThreads()637 public final boolean hasQueuedThreads() { 638 return sync.hasQueuedThreads(); 639 } 640 641 /** 642 * Returns an estimate of the number of threads waiting to acquire. 643 * The value is only an estimate because the number of threads may 644 * change dynamically while this method traverses internal data 645 * structures. This method is designed for use in monitoring of the 646 * system state, not for synchronization control. 647 * 648 * @return the estimated number of threads waiting for this lock 649 */ getQueueLength()650 public final int getQueueLength() { 651 return sync.getQueueLength(); 652 } 653 654 /** 655 * Returns a collection containing threads that may be waiting to acquire. 656 * Because the actual set of threads may change dynamically while 657 * constructing this result, the returned collection is only a best-effort 658 * estimate. The elements of the returned collection are in no particular 659 * order. This method is designed to facilitate construction of 660 * subclasses that provide more extensive monitoring facilities. 661 * 662 * @return the collection of threads 663 */ getQueuedThreads()664 protected Collection<Thread> getQueuedThreads() { 665 return sync.getQueuedThreads(); 666 } 667 668 /** 669 * Returns a string identifying this semaphore, as well as its state. 670 * The state, in brackets, includes the String {@code "Permits ="} 671 * followed by the number of permits. 672 * 673 * @return a string identifying this semaphore, as well as its state 674 */ toString()675 public String toString() { 676 return super.toString() + "[Permits = " + sync.getPermits() + "]"; 677 } 678 } 679