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.locks; 8 9 import java.util.Collection; 10 import java.util.concurrent.TimeUnit; 11 /// OPENJDK-9 import jdk.internal.vm.annotation.ReservedStackAccess; 12 13 /** 14 * A reentrant mutual exclusion {@link Lock} with the same basic 15 * behavior and semantics as the implicit monitor lock accessed using 16 * {@code synchronized} methods and statements, but with extended 17 * capabilities. 18 * 19 * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last 20 * successfully locking, but not yet unlocking it. A thread invoking 21 * {@code lock} will return, successfully acquiring the lock, when 22 * the lock is not owned by another thread. The method will return 23 * immediately if the current thread already owns the lock. This can 24 * be checked using methods {@link #isHeldByCurrentThread}, and {@link 25 * #getHoldCount}. 26 * 27 * <p>The constructor for this class accepts an optional 28 * <em>fairness</em> parameter. When set {@code true}, under 29 * contention, locks favor granting access to the longest-waiting 30 * thread. Otherwise this lock does not guarantee any particular 31 * access order. Programs using fair locks accessed by many threads 32 * may display lower overall throughput (i.e., are slower; often much 33 * slower) than those using the default setting, but have smaller 34 * variances in times to obtain locks and guarantee lack of 35 * starvation. Note however, that fairness of locks does not guarantee 36 * fairness of thread scheduling. Thus, one of many threads using a 37 * fair lock may obtain it multiple times in succession while other 38 * active threads are not progressing and not currently holding the 39 * lock. 40 * Also note that the untimed {@link #tryLock()} method does not 41 * honor the fairness setting. It will succeed if the lock 42 * is available even if other threads are waiting. 43 * 44 * <p>It is recommended practice to <em>always</em> immediately 45 * follow a call to {@code lock} with a {@code try} block, most 46 * typically in a before/after construction such as: 47 * 48 * <pre> {@code 49 * class X { 50 * private final ReentrantLock lock = new ReentrantLock(); 51 * // ... 52 * 53 * public void m() { 54 * lock.lock(); // block until condition holds 55 * try { 56 * // ... method body 57 * } finally { 58 * lock.unlock() 59 * } 60 * } 61 * }}</pre> 62 * 63 * <p>In addition to implementing the {@link Lock} interface, this 64 * class defines a number of {@code public} and {@code protected} 65 * methods for inspecting the state of the lock. Some of these 66 * methods are only useful for instrumentation and monitoring. 67 * 68 * <p>Serialization of this class behaves in the same way as built-in 69 * locks: a deserialized lock is in the unlocked state, regardless of 70 * its state when serialized. 71 * 72 * <p>This lock supports a maximum of 2147483647 recursive locks by 73 * the same thread. Attempts to exceed this limit result in 74 * {@link Error} throws from locking methods. 75 * 76 * @since 1.5 77 * @author Doug Lea 78 */ 79 public class ReentrantLock implements Lock, java.io.Serializable { 80 private static final long serialVersionUID = 7373984872572414699L; 81 /** Synchronizer providing all implementation mechanics */ 82 private final Sync sync; 83 84 /** 85 * Base of synchronization control for this lock. Subclassed 86 * into fair and nonfair versions below. Uses AQS state to 87 * represent the number of holds on the lock. 88 */ 89 abstract static class Sync extends AbstractQueuedSynchronizer { 90 private static final long serialVersionUID = -5179523762034025860L; 91 92 /** 93 * Performs {@link Lock#lock}. The main reason for subclassing 94 * is to allow fast path for nonfair version. 95 */ lock()96 abstract void lock(); 97 98 /** 99 * Performs non-fair tryLock. tryAcquire is implemented in 100 * subclasses, but both need nonfair try for trylock method. 101 */ 102 /// OPENJDK-9 @ReservedStackAccess nonfairTryAcquire(int acquires)103 final boolean nonfairTryAcquire(int acquires) { 104 final Thread current = Thread.currentThread(); 105 int c = getState(); 106 if (c == 0) { 107 if (compareAndSetState(0, acquires)) { 108 setExclusiveOwnerThread(current); 109 return true; 110 } 111 } 112 else if (current == getExclusiveOwnerThread()) { 113 int nextc = c + acquires; 114 if (nextc < 0) // overflow 115 throw new Error("Maximum lock count exceeded"); 116 setState(nextc); 117 return true; 118 } 119 return false; 120 } 121 122 /// OPENJDK-9 @ReservedStackAccess tryRelease(int releases)123 protected final boolean tryRelease(int releases) { 124 int c = getState() - releases; 125 if (Thread.currentThread() != getExclusiveOwnerThread()) 126 throw new IllegalMonitorStateException(); 127 boolean free = false; 128 if (c == 0) { 129 free = true; 130 setExclusiveOwnerThread(null); 131 } 132 setState(c); 133 return free; 134 } 135 isHeldExclusively()136 protected final boolean isHeldExclusively() { 137 // While we must in general read state before owner, 138 // we don't need to do so to check if current thread is owner 139 return getExclusiveOwnerThread() == Thread.currentThread(); 140 } 141 newCondition()142 final ConditionObject newCondition() { 143 return new ConditionObject(); 144 } 145 146 // Methods relayed from outer class 147 getOwner()148 final Thread getOwner() { 149 return getState() == 0 ? null : getExclusiveOwnerThread(); 150 } 151 getHoldCount()152 final int getHoldCount() { 153 return isHeldExclusively() ? getState() : 0; 154 } 155 isLocked()156 final boolean isLocked() { 157 return getState() != 0; 158 } 159 160 /** 161 * Reconstitutes the instance from a stream (that is, deserializes it). 162 */ readObject(java.io.ObjectInputStream s)163 private void readObject(java.io.ObjectInputStream s) 164 throws java.io.IOException, ClassNotFoundException { 165 s.defaultReadObject(); 166 setState(0); // reset to unlocked state 167 } 168 } 169 170 /** 171 * Sync object for non-fair locks 172 */ 173 static final class NonfairSync extends Sync { 174 private static final long serialVersionUID = 7316153563782823691L; 175 176 /** 177 * Performs lock. Try immediate barge, backing up to normal 178 * acquire on failure. 179 */ 180 /// OPENJDK-9 @ReservedStackAccess lock()181 final void lock() { 182 if (compareAndSetState(0, 1)) 183 setExclusiveOwnerThread(Thread.currentThread()); 184 else 185 acquire(1); 186 } 187 tryAcquire(int acquires)188 protected final boolean tryAcquire(int acquires) { 189 return nonfairTryAcquire(acquires); 190 } 191 } 192 193 /** 194 * Sync object for fair locks 195 */ 196 static final class FairSync extends Sync { 197 private static final long serialVersionUID = -3000897897090466540L; 198 lock()199 final void lock() { 200 acquire(1); 201 } 202 203 /** 204 * Fair version of tryAcquire. Don't grant access unless 205 * recursive call or no waiters or is first. 206 */ 207 /// OPENJDK-9 @ReservedStackAccess tryAcquire(int acquires)208 protected final boolean tryAcquire(int acquires) { 209 final Thread current = Thread.currentThread(); 210 int c = getState(); 211 if (c == 0) { 212 if (!hasQueuedPredecessors() && 213 compareAndSetState(0, acquires)) { 214 setExclusiveOwnerThread(current); 215 return true; 216 } 217 } 218 else if (current == getExclusiveOwnerThread()) { 219 int nextc = c + acquires; 220 if (nextc < 0) 221 throw new Error("Maximum lock count exceeded"); 222 setState(nextc); 223 return true; 224 } 225 return false; 226 } 227 } 228 229 /** 230 * Creates an instance of {@code ReentrantLock}. 231 * This is equivalent to using {@code ReentrantLock(false)}. 232 */ ReentrantLock()233 public ReentrantLock() { 234 sync = new NonfairSync(); 235 } 236 237 /** 238 * Creates an instance of {@code ReentrantLock} with the 239 * given fairness policy. 240 * 241 * @param fair {@code true} if this lock should use a fair ordering policy 242 */ ReentrantLock(boolean fair)243 public ReentrantLock(boolean fair) { 244 sync = fair ? new FairSync() : new NonfairSync(); 245 } 246 247 /** 248 * Acquires the lock. 249 * 250 * <p>Acquires the lock if it is not held by another thread and returns 251 * immediately, setting the lock hold count to one. 252 * 253 * <p>If the current thread already holds the lock then the hold 254 * count is incremented by one and the method returns immediately. 255 * 256 * <p>If the lock is held by another thread then the 257 * current thread becomes disabled for thread scheduling 258 * purposes and lies dormant until the lock has been acquired, 259 * at which time the lock hold count is set to one. 260 */ lock()261 public void lock() { 262 sync.lock(); 263 } 264 265 /** 266 * Acquires the lock unless the current thread is 267 * {@linkplain Thread#interrupt interrupted}. 268 * 269 * <p>Acquires the lock if it is not held by another thread and returns 270 * immediately, setting the lock hold count to one. 271 * 272 * <p>If the current thread already holds this lock then the hold count 273 * is incremented by one and the method returns immediately. 274 * 275 * <p>If the lock is held by another thread then the 276 * current thread becomes disabled for thread scheduling 277 * purposes and lies dormant until one of two things happens: 278 * 279 * <ul> 280 * 281 * <li>The lock is acquired by the current thread; or 282 * 283 * <li>Some other thread {@linkplain Thread#interrupt interrupts} the 284 * current thread. 285 * 286 * </ul> 287 * 288 * <p>If the lock is acquired by the current thread then the lock hold 289 * count is set to one. 290 * 291 * <p>If the current thread: 292 * 293 * <ul> 294 * 295 * <li>has its interrupted status set on entry to this method; or 296 * 297 * <li>is {@linkplain Thread#interrupt interrupted} while acquiring 298 * the lock, 299 * 300 * </ul> 301 * 302 * then {@link InterruptedException} is thrown and the current thread's 303 * interrupted status is cleared. 304 * 305 * <p>In this implementation, as this method is an explicit 306 * interruption point, preference is given to responding to the 307 * interrupt over normal or reentrant acquisition of the lock. 308 * 309 * @throws InterruptedException if the current thread is interrupted 310 */ lockInterruptibly()311 public void lockInterruptibly() throws InterruptedException { 312 sync.acquireInterruptibly(1); 313 } 314 315 /** 316 * Acquires the lock only if it is not held by another thread at the time 317 * of invocation. 318 * 319 * <p>Acquires the lock if it is not held by another thread and 320 * returns immediately with the value {@code true}, setting the 321 * lock hold count to one. Even when this lock has been set to use a 322 * fair ordering policy, a call to {@code tryLock()} <em>will</em> 323 * immediately acquire the lock if it is available, whether or not 324 * other threads are currently waiting for the lock. 325 * This "barging" behavior can be useful in certain 326 * circumstances, even though it breaks fairness. If you want to honor 327 * the fairness setting for this lock, then use 328 * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } 329 * which is almost equivalent (it also detects interruption). 330 * 331 * <p>If the current thread already holds this lock then the hold 332 * count is incremented by one and the method returns {@code true}. 333 * 334 * <p>If the lock is held by another thread then this method will return 335 * immediately with the value {@code false}. 336 * 337 * @return {@code true} if the lock was free and was acquired by the 338 * current thread, or the lock was already held by the current 339 * thread; and {@code false} otherwise 340 */ tryLock()341 public boolean tryLock() { 342 return sync.nonfairTryAcquire(1); 343 } 344 345 /** 346 * Acquires the lock if it is not held by another thread within the given 347 * waiting time and the current thread has not been 348 * {@linkplain Thread#interrupt interrupted}. 349 * 350 * <p>Acquires the lock if it is not held by another thread and returns 351 * immediately with the value {@code true}, setting the lock hold count 352 * to one. If this lock has been set to use a fair ordering policy then 353 * an available lock <em>will not</em> be acquired if any other threads 354 * are waiting for the lock. This is in contrast to the {@link #tryLock()} 355 * method. If you want a timed {@code tryLock} that does permit barging on 356 * a fair lock then combine the timed and un-timed forms together: 357 * 358 * <pre> {@code 359 * if (lock.tryLock() || 360 * lock.tryLock(timeout, unit)) { 361 * ... 362 * }}</pre> 363 * 364 * <p>If the current thread 365 * already holds this lock then the hold count is incremented by one and 366 * the method returns {@code true}. 367 * 368 * <p>If the lock is held by another thread then the 369 * current thread becomes disabled for thread scheduling 370 * purposes and lies dormant until one of three things happens: 371 * 372 * <ul> 373 * 374 * <li>The lock is acquired by the current thread; or 375 * 376 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 377 * the current thread; or 378 * 379 * <li>The specified waiting time elapses 380 * 381 * </ul> 382 * 383 * <p>If the lock is acquired then the value {@code true} is returned and 384 * the lock hold count is set to one. 385 * 386 * <p>If the current thread: 387 * 388 * <ul> 389 * 390 * <li>has its interrupted status set on entry to this method; or 391 * 392 * <li>is {@linkplain Thread#interrupt interrupted} while 393 * acquiring the lock, 394 * 395 * </ul> 396 * then {@link InterruptedException} is thrown and the current thread's 397 * interrupted status is cleared. 398 * 399 * <p>If the specified waiting time elapses then the value {@code false} 400 * is returned. If the time is less than or equal to zero, the method 401 * will not wait at all. 402 * 403 * <p>In this implementation, as this method is an explicit 404 * interruption point, preference is given to responding to the 405 * interrupt over normal or reentrant acquisition of the lock, and 406 * over reporting the elapse of the waiting time. 407 * 408 * @param timeout the time to wait for the lock 409 * @param unit the time unit of the timeout argument 410 * @return {@code true} if the lock was free and was acquired by the 411 * current thread, or the lock was already held by the current 412 * thread; and {@code false} if the waiting time elapsed before 413 * the lock could be acquired 414 * @throws InterruptedException if the current thread is interrupted 415 * @throws NullPointerException if the time unit is null 416 */ tryLock(long timeout, TimeUnit unit)417 public boolean tryLock(long timeout, TimeUnit unit) 418 throws InterruptedException { 419 return sync.tryAcquireNanos(1, unit.toNanos(timeout)); 420 } 421 422 /** 423 * Attempts to release this lock. 424 * 425 * <p>If the current thread is the holder of this lock then the hold 426 * count is decremented. If the hold count is now zero then the lock 427 * is released. If the current thread is not the holder of this 428 * lock then {@link IllegalMonitorStateException} is thrown. 429 * 430 * @throws IllegalMonitorStateException if the current thread does not 431 * hold this lock 432 */ unlock()433 public void unlock() { 434 sync.release(1); 435 } 436 437 /** 438 * Returns a {@link Condition} instance for use with this 439 * {@link Lock} instance. 440 * 441 * <p>The returned {@link Condition} instance supports the same 442 * usages as do the {@link Object} monitor methods ({@link 443 * Object#wait() wait}, {@link Object#notify notify}, and {@link 444 * Object#notifyAll notifyAll}) when used with the built-in 445 * monitor lock. 446 * 447 * <ul> 448 * 449 * <li>If this lock is not held when any of the {@link Condition} 450 * {@linkplain Condition#await() waiting} or {@linkplain 451 * Condition#signal signalling} methods are called, then an {@link 452 * IllegalMonitorStateException} is thrown. 453 * 454 * <li>When the condition {@linkplain Condition#await() waiting} 455 * methods are called the lock is released and, before they 456 * return, the lock is reacquired and the lock hold count restored 457 * to what it was when the method was called. 458 * 459 * <li>If a thread is {@linkplain Thread#interrupt interrupted} 460 * while waiting then the wait will terminate, an {@link 461 * InterruptedException} will be thrown, and the thread's 462 * interrupted status will be cleared. 463 * 464 * <li>Waiting threads are signalled in FIFO order. 465 * 466 * <li>The ordering of lock reacquisition for threads returning 467 * from waiting methods is the same as for threads initially 468 * acquiring the lock, which is in the default case not specified, 469 * but for <em>fair</em> locks favors those threads that have been 470 * waiting the longest. 471 * 472 * </ul> 473 * 474 * @return the Condition object 475 */ newCondition()476 public Condition newCondition() { 477 return sync.newCondition(); 478 } 479 480 /** 481 * Queries the number of holds on this lock by the current thread. 482 * 483 * <p>A thread has a hold on a lock for each lock action that is not 484 * matched by an unlock action. 485 * 486 * <p>The hold count information is typically only used for testing and 487 * debugging purposes. For example, if a certain section of code should 488 * not be entered with the lock already held then we can assert that 489 * fact: 490 * 491 * <pre> {@code 492 * class X { 493 * ReentrantLock lock = new ReentrantLock(); 494 * // ... 495 * public void m() { 496 * assert lock.getHoldCount() == 0; 497 * lock.lock(); 498 * try { 499 * // ... method body 500 * } finally { 501 * lock.unlock(); 502 * } 503 * } 504 * }}</pre> 505 * 506 * @return the number of holds on this lock by the current thread, 507 * or zero if this lock is not held by the current thread 508 */ getHoldCount()509 public int getHoldCount() { 510 return sync.getHoldCount(); 511 } 512 513 /** 514 * Queries if this lock is held by the current thread. 515 * 516 * <p>Analogous to the {@link Thread#holdsLock(Object)} method for 517 * built-in monitor locks, this method is typically used for 518 * debugging and testing. For example, a method that should only be 519 * called while a lock is held can assert that this is the case: 520 * 521 * <pre> {@code 522 * class X { 523 * ReentrantLock lock = new ReentrantLock(); 524 * // ... 525 * 526 * public void m() { 527 * assert lock.isHeldByCurrentThread(); 528 * // ... method body 529 * } 530 * }}</pre> 531 * 532 * <p>It can also be used to ensure that a reentrant lock is used 533 * in a non-reentrant manner, for example: 534 * 535 * <pre> {@code 536 * class X { 537 * ReentrantLock lock = new ReentrantLock(); 538 * // ... 539 * 540 * public void m() { 541 * assert !lock.isHeldByCurrentThread(); 542 * lock.lock(); 543 * try { 544 * // ... method body 545 * } finally { 546 * lock.unlock(); 547 * } 548 * } 549 * }}</pre> 550 * 551 * @return {@code true} if current thread holds this lock and 552 * {@code false} otherwise 553 */ isHeldByCurrentThread()554 public boolean isHeldByCurrentThread() { 555 return sync.isHeldExclusively(); 556 } 557 558 /** 559 * Queries if this lock is held by any thread. This method is 560 * designed for use in monitoring of the system state, 561 * not for synchronization control. 562 * 563 * @return {@code true} if any thread holds this lock and 564 * {@code false} otherwise 565 */ isLocked()566 public boolean isLocked() { 567 return sync.isLocked(); 568 } 569 570 /** 571 * Returns {@code true} if this lock has fairness set true. 572 * 573 * @return {@code true} if this lock has fairness set true 574 */ isFair()575 public final boolean isFair() { 576 return sync instanceof FairSync; 577 } 578 579 /** 580 * Returns the thread that currently owns this lock, or 581 * {@code null} if not owned. When this method is called by a 582 * thread that is not the owner, the return value reflects a 583 * best-effort approximation of current lock status. For example, 584 * the owner may be momentarily {@code null} even if there are 585 * threads trying to acquire the lock but have not yet done so. 586 * This method is designed to facilitate construction of 587 * subclasses that provide more extensive lock monitoring 588 * facilities. 589 * 590 * @return the owner, or {@code null} if not owned 591 */ getOwner()592 protected Thread getOwner() { 593 return sync.getOwner(); 594 } 595 596 /** 597 * Queries whether any threads are waiting to acquire this lock. Note that 598 * because cancellations may occur at any time, a {@code true} 599 * return does not guarantee that any other thread will ever 600 * acquire this lock. This method is designed primarily for use in 601 * monitoring of the system state. 602 * 603 * @return {@code true} if there may be other threads waiting to 604 * acquire the lock 605 */ hasQueuedThreads()606 public final boolean hasQueuedThreads() { 607 return sync.hasQueuedThreads(); 608 } 609 610 /** 611 * Queries whether the given thread is waiting to acquire this 612 * lock. Note that because cancellations may occur at any time, a 613 * {@code true} return does not guarantee that this thread 614 * will ever acquire this lock. This method is designed primarily for use 615 * in monitoring of the system state. 616 * 617 * @param thread the thread 618 * @return {@code true} if the given thread is queued waiting for this lock 619 * @throws NullPointerException if the thread is null 620 */ hasQueuedThread(Thread thread)621 public final boolean hasQueuedThread(Thread thread) { 622 return sync.isQueued(thread); 623 } 624 625 /** 626 * Returns an estimate of the number of threads waiting to acquire 627 * this lock. The value is only an estimate because the number of 628 * threads may change dynamically while this method traverses 629 * internal data structures. This method is designed for use in 630 * monitoring system state, not for synchronization control. 631 * 632 * @return the estimated number of threads waiting for this lock 633 */ getQueueLength()634 public final int getQueueLength() { 635 return sync.getQueueLength(); 636 } 637 638 /** 639 * Returns a collection containing threads that may be waiting to 640 * acquire this lock. Because the actual set of threads may change 641 * dynamically while constructing this result, the returned 642 * collection is only a best-effort estimate. The elements of the 643 * returned collection are in no particular order. This method is 644 * designed to facilitate construction of subclasses that provide 645 * more extensive monitoring facilities. 646 * 647 * @return the collection of threads 648 */ getQueuedThreads()649 protected Collection<Thread> getQueuedThreads() { 650 return sync.getQueuedThreads(); 651 } 652 653 /** 654 * Queries whether any threads are waiting on the given condition 655 * associated with this lock. Note that because timeouts and 656 * interrupts may occur at any time, a {@code true} return does 657 * not guarantee that a future {@code signal} will awaken any 658 * threads. This method is designed primarily for use in 659 * monitoring of the system state. 660 * 661 * @param condition the condition 662 * @return {@code true} if there are any waiting threads 663 * @throws IllegalMonitorStateException if this lock is not held 664 * @throws IllegalArgumentException if the given condition is 665 * not associated with this lock 666 * @throws NullPointerException if the condition is null 667 */ hasWaiters(Condition condition)668 public boolean hasWaiters(Condition condition) { 669 if (condition == null) 670 throw new NullPointerException(); 671 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 672 throw new IllegalArgumentException("not owner"); 673 return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); 674 } 675 676 /** 677 * Returns an estimate of the number of threads waiting on the 678 * given condition associated with this lock. Note that because 679 * timeouts and interrupts may occur at any time, the estimate 680 * serves only as an upper bound on the actual number of waiters. 681 * This method is designed for use in monitoring of the system 682 * state, not for synchronization control. 683 * 684 * @param condition the condition 685 * @return the estimated number of waiting threads 686 * @throws IllegalMonitorStateException if this lock is not held 687 * @throws IllegalArgumentException if the given condition is 688 * not associated with this lock 689 * @throws NullPointerException if the condition is null 690 */ getWaitQueueLength(Condition condition)691 public int getWaitQueueLength(Condition condition) { 692 if (condition == null) 693 throw new NullPointerException(); 694 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 695 throw new IllegalArgumentException("not owner"); 696 return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); 697 } 698 699 /** 700 * Returns a collection containing those threads that may be 701 * waiting on the given condition associated with this lock. 702 * Because the actual set of threads may change dynamically while 703 * constructing this result, the returned collection is only a 704 * best-effort estimate. The elements of the returned collection 705 * are in no particular order. This method is designed to 706 * facilitate construction of subclasses that provide more 707 * extensive condition monitoring facilities. 708 * 709 * @param condition the condition 710 * @return the collection of threads 711 * @throws IllegalMonitorStateException if this lock is not held 712 * @throws IllegalArgumentException if the given condition is 713 * not associated with this lock 714 * @throws NullPointerException if the condition is null 715 */ getWaitingThreads(Condition condition)716 protected Collection<Thread> getWaitingThreads(Condition condition) { 717 if (condition == null) 718 throw new NullPointerException(); 719 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 720 throw new IllegalArgumentException("not owner"); 721 return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); 722 } 723 724 /** 725 * Returns a string identifying this lock, as well as its lock state. 726 * The state, in brackets, includes either the String {@code "Unlocked"} 727 * or the String {@code "Locked by"} followed by the 728 * {@linkplain Thread#getName name} of the owning thread. 729 * 730 * @return a string identifying this lock, as well as its lock state 731 */ toString()732 public String toString() { 733 Thread o = sync.getOwner(); 734 return super.toString() + ((o == null) ? 735 "[Unlocked]" : 736 "[Locked by thread " + o.getName() + "]"); 737 } 738 } 739