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