1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/licenses/publicdomain 34 */ 35 36 package java.util.concurrent.locks; 37 import java.util.concurrent.*; 38 import java.util.concurrent.atomic.*; 39 import java.util.*; 40 41 /** 42 * An implementation of {@link ReadWriteLock} supporting similar 43 * semantics to {@link ReentrantLock}. 44 * <p>This class has the following properties: 45 * 46 * <ul> 47 * <li><b>Acquisition order</b> 48 * 49 * <p> This class does not impose a reader or writer preference 50 * ordering for lock access. However, it does support an optional 51 * <em>fairness</em> policy. 52 * 53 * <dl> 54 * <dt><b><i>Non-fair mode (default)</i></b> 55 * <dd>When constructed as non-fair (the default), the order of entry 56 * to the read and write lock is unspecified, subject to reentrancy 57 * constraints. A nonfair lock that is continuously contended may 58 * indefinitely postpone one or more reader or writer threads, but 59 * will normally have higher throughput than a fair lock. 60 * <p> 61 * 62 * <dt><b><i>Fair mode</i></b> 63 * <dd> When constructed as fair, threads contend for entry using an 64 * approximately arrival-order policy. When the currently held lock 65 * is released either the longest-waiting single writer thread will 66 * be assigned the write lock, or if there is a group of reader threads 67 * waiting longer than all waiting writer threads, that group will be 68 * assigned the read lock. 69 * 70 * <p>A thread that tries to acquire a fair read lock (non-reentrantly) 71 * will block if either the write lock is held, or there is a waiting 72 * writer thread. The thread will not acquire the read lock until 73 * after the oldest currently waiting writer thread has acquired and 74 * released the write lock. Of course, if a waiting writer abandons 75 * its wait, leaving one or more reader threads as the longest waiters 76 * in the queue with the write lock free, then those readers will be 77 * assigned the read lock. 78 * 79 * <p>A thread that tries to acquire a fair write lock (non-reentrantly) 80 * will block unless both the read lock and write lock are free (which 81 * implies there are no waiting threads). (Note that the non-blocking 82 * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods 83 * do not honor this fair setting and will acquire the lock if it is 84 * possible, regardless of waiting threads.) 85 * <p> 86 * </dl> 87 * 88 * <li><b>Reentrancy</b> 89 * 90 * <p>This lock allows both readers and writers to reacquire read or 91 * write locks in the style of a {@link ReentrantLock}. Non-reentrant 92 * readers are not allowed until all write locks held by the writing 93 * thread have been released. 94 * 95 * <p>Additionally, a writer can acquire the read lock, but not 96 * vice-versa. Among other applications, reentrancy can be useful 97 * when write locks are held during calls or callbacks to methods that 98 * perform reads under read locks. If a reader tries to acquire the 99 * write lock it will never succeed. 100 * 101 * <li><b>Lock downgrading</b> 102 * <p>Reentrancy also allows downgrading from the write lock to a read lock, 103 * by acquiring the write lock, then the read lock and then releasing the 104 * write lock. However, upgrading from a read lock to the write lock is 105 * <b>not</b> possible. 106 * 107 * <li><b>Interruption of lock acquisition</b> 108 * <p>The read lock and write lock both support interruption during lock 109 * acquisition. 110 * 111 * <li><b>{@link Condition} support</b> 112 * <p>The write lock provides a {@link Condition} implementation that 113 * behaves in the same way, with respect to the write lock, as the 114 * {@link Condition} implementation provided by 115 * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}. 116 * This {@link Condition} can, of course, only be used with the write lock. 117 * 118 * <p>The read lock does not support a {@link Condition} and 119 * {@code readLock().newCondition()} throws 120 * {@code UnsupportedOperationException}. 121 * 122 * <li><b>Instrumentation</b> 123 * <p>This class supports methods to determine whether locks 124 * are held or contended. These methods are designed for monitoring 125 * system state, not for synchronization control. 126 * </ul> 127 * 128 * <p>Serialization of this class behaves in the same way as built-in 129 * locks: a deserialized lock is in the unlocked state, regardless of 130 * its state when serialized. 131 * 132 * <p><b>Sample usages</b>. Here is a code sketch showing how to perform 133 * lock downgrading after updating a cache (exception handling is 134 * particularly tricky when handling multiple locks in a non-nested 135 * fashion): 136 * 137 * <pre> {@code 138 * class CachedData { 139 * Object data; 140 * volatile boolean cacheValid; 141 * final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 142 * 143 * void processCachedData() { 144 * rwl.readLock().lock(); 145 * if (!cacheValid) { 146 * // Must release read lock before acquiring write lock 147 * rwl.readLock().unlock(); 148 * rwl.writeLock().lock(); 149 * try { 150 * // Recheck state because another thread might have 151 * // acquired write lock and changed state before we did. 152 * if (!cacheValid) { 153 * data = ... 154 * cacheValid = true; 155 * } 156 * // Downgrade by acquiring read lock before releasing write lock 157 * rwl.readLock().lock(); 158 * } finally { 159 * rwl.writeLock().unlock(); // Unlock write, still hold read 160 * } 161 * } 162 * 163 * try { 164 * use(data); 165 * } finally { 166 * rwl.readLock().unlock(); 167 * } 168 * } 169 * }}</pre> 170 * 171 * ReentrantReadWriteLocks can be used to improve concurrency in some 172 * uses of some kinds of Collections. This is typically worthwhile 173 * only when the collections are expected to be large, accessed by 174 * more reader threads than writer threads, and entail operations with 175 * overhead that outweighs synchronization overhead. For example, here 176 * is a class using a TreeMap that is expected to be large and 177 * concurrently accessed. 178 * 179 * <pre>{@code 180 * class RWDictionary { 181 * private final Map<String, Data> m = new TreeMap<String, Data>(); 182 * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 183 * private final Lock r = rwl.readLock(); 184 * private final Lock w = rwl.writeLock(); 185 * 186 * public Data get(String key) { 187 * r.lock(); 188 * try { return m.get(key); } 189 * finally { r.unlock(); } 190 * } 191 * public String[] allKeys() { 192 * r.lock(); 193 * try { return m.keySet().toArray(); } 194 * finally { r.unlock(); } 195 * } 196 * public Data put(String key, Data value) { 197 * w.lock(); 198 * try { return m.put(key, value); } 199 * finally { w.unlock(); } 200 * } 201 * public void clear() { 202 * w.lock(); 203 * try { m.clear(); } 204 * finally { w.unlock(); } 205 * } 206 * }}</pre> 207 * 208 * <h3>Implementation Notes</h3> 209 * 210 * <p>This lock supports a maximum of 65535 recursive write locks 211 * and 65535 read locks. Attempts to exceed these limits result in 212 * {@link Error} throws from locking methods. 213 * 214 * @since 1.5 215 * @author Doug Lea 216 * 217 */ 218 public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { 219 private static final long serialVersionUID = -6992448646407690164L; 220 /** Inner class providing readlock */ 221 private final ReentrantReadWriteLock.ReadLock readerLock; 222 /** Inner class providing writelock */ 223 private final ReentrantReadWriteLock.WriteLock writerLock; 224 /** Performs all synchronization mechanics */ 225 final Sync sync; 226 227 /** 228 * Creates a new {@code ReentrantReadWriteLock} with 229 * default (nonfair) ordering properties. 230 */ 231 public ReentrantReadWriteLock() { 232 this(false); 233 } 234 235 /** 236 * Creates a new {@code ReentrantReadWriteLock} with 237 * the given fairness policy. 238 * 239 * @param fair {@code true} if this lock should use a fair ordering policy 240 */ 241 public ReentrantReadWriteLock(boolean fair) { 242 sync = fair ? new FairSync() : new NonfairSync(); 243 readerLock = new ReadLock(this); 244 writerLock = new WriteLock(this); 245 } 246 247 public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; } 248 public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; } 249 250 /** 251 * Synchronization implementation for ReentrantReadWriteLock. 252 * Subclassed into fair and nonfair versions. 253 */ 254 static abstract class Sync extends AbstractQueuedSynchronizer { 255 private static final long serialVersionUID = 6317671515068378041L; 256 257 /* 258 * Read vs write count extraction constants and functions. 259 * Lock state is logically divided into two unsigned shorts: 260 * The lower one representing the exclusive (writer) lock hold count, 261 * and the upper the shared (reader) hold count. 262 */ 263 264 static final int SHARED_SHIFT = 16; 265 static final int SHARED_UNIT = (1 << SHARED_SHIFT); 266 static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1; 267 static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; 268 269 /** Returns the number of shared holds represented in count */ 270 static int sharedCount(int c) { return c >>> SHARED_SHIFT; } 271 /** Returns the number of exclusive holds represented in count */ 272 static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; } 273 274 /** 275 * A counter for per-thread read hold counts. 276 * Maintained as a ThreadLocal; cached in cachedHoldCounter 277 */ 278 static final class HoldCounter { 279 int count = 0; 280 // Use id, not reference, to avoid garbage retention 281 final long tid = Thread.currentThread().getId(); 282 } 283 284 /** 285 * ThreadLocal subclass. Easiest to explicitly define for sake 286 * of deserialization mechanics. 287 */ 288 static final class ThreadLocalHoldCounter 289 extends ThreadLocal<HoldCounter> { 290 public HoldCounter initialValue() { 291 return new HoldCounter(); 292 } 293 } 294 295 /** 296 * The number of reentrant read locks held by current thread. 297 * Initialized only in constructor and readObject. 298 * Removed whenever a thread's read hold count drops to 0. 299 */ 300 private transient ThreadLocalHoldCounter readHolds; 301 302 /** 303 * The hold count of the last thread to successfully acquire 304 * readLock. This saves ThreadLocal lookup in the common case 305 * where the next thread to release is the last one to 306 * acquire. This is non-volatile since it is just used 307 * as a heuristic, and would be great for threads to cache. 308 * 309 * <p>Can outlive the Thread for which it is caching the read 310 * hold count, but avoids garbage retention by not retaining a 311 * reference to the Thread. 312 * 313 * <p>Accessed via a benign data race; relies on the memory 314 * model's final field and out-of-thin-air guarantees. 315 */ 316 private transient HoldCounter cachedHoldCounter; 317 318 /** 319 * firstReader is the first thread to have acquired the read lock. 320 * firstReaderHoldCount is firstReader's hold count. 321 * 322 * <p>More precisely, firstReader is the unique thread that last 323 * changed the shared count from 0 to 1, and has not released the 324 * read lock since then; null if there is no such thread. 325 * 326 * <p>Cannot cause garbage retention unless the thread terminated 327 * without relinquishing its read locks, since tryReleaseShared 328 * sets it to null. 329 * 330 * <p>Accessed via a benign data race; relies on the memory 331 * model's out-of-thin-air guarantees for references. 332 * 333 * <p>This allows tracking of read holds for uncontended read 334 * locks to be very cheap. 335 */ 336 private transient Thread firstReader = null; 337 private transient int firstReaderHoldCount; 338 339 Sync() { 340 readHolds = new ThreadLocalHoldCounter(); 341 setState(getState()); // ensures visibility of readHolds 342 } 343 344 /* 345 * Acquires and releases use the same code for fair and 346 * nonfair locks, but differ in whether/how they allow barging 347 * when queues are non-empty. 348 */ 349 350 /** 351 * Returns true if the current thread, when trying to acquire 352 * the read lock, and otherwise eligible to do so, should block 353 * because of policy for overtaking other waiting threads. 354 */ 355 abstract boolean readerShouldBlock(); 356 357 /** 358 * Returns true if the current thread, when trying to acquire 359 * the write lock, and otherwise eligible to do so, should block 360 * because of policy for overtaking other waiting threads. 361 */ 362 abstract boolean writerShouldBlock(); 363 364 /* 365 * Note that tryRelease and tryAcquire can be called by 366 * Conditions. So it is possible that their arguments contain 367 * both read and write holds that are all released during a 368 * condition wait and re-established in tryAcquire. 369 */ 370 371 protected final boolean tryRelease(int releases) { 372 if (!isHeldExclusively()) 373 throw new IllegalMonitorStateException(); 374 int nextc = getState() - releases; 375 boolean free = exclusiveCount(nextc) == 0; 376 if (free) 377 setExclusiveOwnerThread(null); 378 setState(nextc); 379 return free; 380 } 381 382 protected final boolean tryAcquire(int acquires) { 383 /* 384 * Walkthrough: 385 * 1. If read count nonzero or write count nonzero 386 * and owner is a different thread, fail. 387 * 2. If count would saturate, fail. (This can only 388 * happen if count is already nonzero.) 389 * 3. Otherwise, this thread is eligible for lock if 390 * it is either a reentrant acquire or 391 * queue policy allows it. If so, update state 392 * and set owner. 393 */ 394 Thread current = Thread.currentThread(); 395 int c = getState(); 396 int w = exclusiveCount(c); 397 if (c != 0) { 398 // (Note: if c != 0 and w == 0 then shared count != 0) 399 if (w == 0 || current != getExclusiveOwnerThread()) 400 return false; 401 if (w + exclusiveCount(acquires) > MAX_COUNT) 402 throw new Error("Maximum lock count exceeded"); 403 // Reentrant acquire 404 setState(c + acquires); 405 return true; 406 } 407 if (writerShouldBlock() || 408 !compareAndSetState(c, c + acquires)) 409 return false; 410 setExclusiveOwnerThread(current); 411 return true; 412 } 413 414 protected final boolean tryReleaseShared(int unused) { 415 Thread current = Thread.currentThread(); 416 if (firstReader == current) { 417 // assert firstReaderHoldCount > 0; 418 if (firstReaderHoldCount == 1) 419 firstReader = null; 420 else 421 firstReaderHoldCount--; 422 } else { 423 HoldCounter rh = cachedHoldCounter; 424 if (rh == null || rh.tid != current.getId()) 425 rh = readHolds.get(); 426 int count = rh.count; 427 if (count <= 1) { 428 readHolds.remove(); 429 if (count <= 0) 430 throw unmatchedUnlockException(); 431 } 432 --rh.count; 433 } 434 for (;;) { 435 int c = getState(); 436 int nextc = c - SHARED_UNIT; 437 if (compareAndSetState(c, nextc)) 438 // Releasing the read lock has no effect on readers, 439 // but it may allow waiting writers to proceed if 440 // both read and write locks are now free. 441 return nextc == 0; 442 } 443 } 444 445 private IllegalMonitorStateException unmatchedUnlockException() { 446 return new IllegalMonitorStateException( 447 "attempt to unlock read lock, not locked by current thread"); 448 } 449 450 protected final int tryAcquireShared(int unused) { 451 /* 452 * Walkthrough: 453 * 1. If write lock held by another thread, fail. 454 * 2. Otherwise, this thread is eligible for 455 * lock wrt state, so ask if it should block 456 * because of queue policy. If not, try 457 * to grant by CASing state and updating count. 458 * Note that step does not check for reentrant 459 * acquires, which is postponed to full version 460 * to avoid having to check hold count in 461 * the more typical non-reentrant case. 462 * 3. If step 2 fails either because thread 463 * apparently not eligible or CAS fails or count 464 * saturated, chain to version with full retry loop. 465 */ 466 Thread current = Thread.currentThread(); 467 int c = getState(); 468 if (exclusiveCount(c) != 0 && 469 getExclusiveOwnerThread() != current) 470 return -1; 471 int r = sharedCount(c); 472 if (!readerShouldBlock() && 473 r < MAX_COUNT && 474 compareAndSetState(c, c + SHARED_UNIT)) { 475 if (r == 0) { 476 firstReader = current; 477 firstReaderHoldCount = 1; 478 } else if (firstReader == current) { 479 firstReaderHoldCount++; 480 } else { 481 HoldCounter rh = cachedHoldCounter; 482 if (rh == null || rh.tid != current.getId()) 483 cachedHoldCounter = rh = readHolds.get(); 484 else if (rh.count == 0) 485 readHolds.set(rh); 486 rh.count++; 487 } 488 return 1; 489 } 490 return fullTryAcquireShared(current); 491 } 492 493 /** 494 * Full version of acquire for reads, that handles CAS misses 495 * and reentrant reads not dealt with in tryAcquireShared. 496 */ 497 final int fullTryAcquireShared(Thread current) { 498 /* 499 * This code is in part redundant with that in 500 * tryAcquireShared but is simpler overall by not 501 * complicating tryAcquireShared with interactions between 502 * retries and lazily reading hold counts. 503 */ 504 HoldCounter rh = null; 505 for (;;) { 506 int c = getState(); 507 if (exclusiveCount(c) != 0) { 508 if (getExclusiveOwnerThread() != current) 509 return -1; 510 // else we hold the exclusive lock; blocking here 511 // would cause deadlock. 512 } else if (readerShouldBlock()) { 513 // Make sure we're not acquiring read lock reentrantly 514 if (firstReader == current) { 515 // assert firstReaderHoldCount > 0; 516 } else { 517 if (rh == null) { 518 rh = cachedHoldCounter; 519 if (rh == null || rh.tid != current.getId()) { 520 rh = readHolds.get(); 521 if (rh.count == 0) 522 readHolds.remove(); 523 } 524 } 525 if (rh.count == 0) 526 return -1; 527 } 528 } 529 if (sharedCount(c) == MAX_COUNT) 530 throw new Error("Maximum lock count exceeded"); 531 if (compareAndSetState(c, c + SHARED_UNIT)) { 532 if (sharedCount(c) == 0) { 533 firstReader = current; 534 firstReaderHoldCount = 1; 535 } else if (firstReader == current) { 536 firstReaderHoldCount++; 537 } else { 538 if (rh == null) 539 rh = cachedHoldCounter; 540 if (rh == null || rh.tid != current.getId()) 541 rh = readHolds.get(); 542 else if (rh.count == 0) 543 readHolds.set(rh); 544 rh.count++; 545 cachedHoldCounter = rh; // cache for release 546 } 547 return 1; 548 } 549 } 550 } 551 552 /** 553 * Performs tryLock for write, enabling barging in both modes. 554 * This is identical in effect to tryAcquire except for lack 555 * of calls to writerShouldBlock. 556 */ 557 final boolean tryWriteLock() { 558 Thread current = Thread.currentThread(); 559 int c = getState(); 560 if (c != 0) { 561 int w = exclusiveCount(c); 562 if (w == 0 || current != getExclusiveOwnerThread()) 563 return false; 564 if (w == MAX_COUNT) 565 throw new Error("Maximum lock count exceeded"); 566 } 567 if (!compareAndSetState(c, c + 1)) 568 return false; 569 setExclusiveOwnerThread(current); 570 return true; 571 } 572 573 /** 574 * Performs tryLock for read, enabling barging in both modes. 575 * This is identical in effect to tryAcquireShared except for 576 * lack of calls to readerShouldBlock. 577 */ 578 final boolean tryReadLock() { 579 Thread current = Thread.currentThread(); 580 for (;;) { 581 int c = getState(); 582 if (exclusiveCount(c) != 0 && 583 getExclusiveOwnerThread() != current) 584 return false; 585 int r = sharedCount(c); 586 if (r == MAX_COUNT) 587 throw new Error("Maximum lock count exceeded"); 588 if (compareAndSetState(c, c + SHARED_UNIT)) { 589 if (r == 0) { 590 firstReader = current; 591 firstReaderHoldCount = 1; 592 } else if (firstReader == current) { 593 firstReaderHoldCount++; 594 } else { 595 HoldCounter rh = cachedHoldCounter; 596 if (rh == null || rh.tid != current.getId()) 597 cachedHoldCounter = rh = readHolds.get(); 598 else if (rh.count == 0) 599 readHolds.set(rh); 600 rh.count++; 601 } 602 return true; 603 } 604 } 605 } 606 607 protected final boolean isHeldExclusively() { 608 // While we must in general read state before owner, 609 // we don't need to do so to check if current thread is owner 610 return getExclusiveOwnerThread() == Thread.currentThread(); 611 } 612 613 // Methods relayed to outer class 614 615 final ConditionObject newCondition() { 616 return new ConditionObject(); 617 } 618 619 final Thread getOwner() { 620 // Must read state before owner to ensure memory consistency 621 return ((exclusiveCount(getState()) == 0)? 622 null : 623 getExclusiveOwnerThread()); 624 } 625 626 final int getReadLockCount() { 627 return sharedCount(getState()); 628 } 629 630 final boolean isWriteLocked() { 631 return exclusiveCount(getState()) != 0; 632 } 633 634 final int getWriteHoldCount() { 635 return isHeldExclusively() ? exclusiveCount(getState()) : 0; 636 } 637 638 final int getReadHoldCount() { 639 if (getReadLockCount() == 0) 640 return 0; 641 642 Thread current = Thread.currentThread(); 643 if (firstReader == current) 644 return firstReaderHoldCount; 645 646 HoldCounter rh = cachedHoldCounter; 647 if (rh != null && rh.tid == current.getId()) 648 return rh.count; 649 650 int count = readHolds.get().count; 651 if (count == 0) readHolds.remove(); 652 return count; 653 } 654 655 /** 656 * Reconstitute this lock instance from a stream 657 * @param s the stream 658 */ 659 private void readObject(java.io.ObjectInputStream s) 660 throws java.io.IOException, ClassNotFoundException { 661 s.defaultReadObject(); 662 readHolds = new ThreadLocalHoldCounter(); 663 setState(0); // reset to unlocked state 664 } 665 666 final int getCount() { return getState(); } 667 } 668 669 /** 670 * Nonfair version of Sync 671 */ 672 final static class NonfairSync extends Sync { 673 private static final long serialVersionUID = -8159625535654395037L; 674 final boolean writerShouldBlock() { 675 return false; // writers can always barge 676 } 677 final boolean readerShouldBlock() { 678 /* As a heuristic to avoid indefinite writer starvation, 679 * block if the thread that momentarily appears to be head 680 * of queue, if one exists, is a waiting writer. This is 681 * only a probabilistic effect since a new reader will not 682 * block if there is a waiting writer behind other enabled 683 * readers that have not yet drained from the queue. 684 */ 685 return apparentlyFirstQueuedIsExclusive(); 686 } 687 } 688 689 /** 690 * Fair version of Sync 691 */ 692 final static class FairSync extends Sync { 693 private static final long serialVersionUID = -2274990926593161451L; 694 final boolean writerShouldBlock() { 695 return hasQueuedPredecessors(); 696 } 697 final boolean readerShouldBlock() { 698 return hasQueuedPredecessors(); 699 } 700 } 701 702 /** 703 * The lock returned by method {@link ReentrantReadWriteLock#readLock}. 704 */ 705 public static class ReadLock implements Lock, java.io.Serializable { 706 private static final long serialVersionUID = -5992448646407690164L; 707 private final Sync sync; 708 709 /** 710 * Constructor for use by subclasses 711 * 712 * @param lock the outer lock object 713 * @throws NullPointerException if the lock is null 714 */ 715 protected ReadLock(ReentrantReadWriteLock lock) { 716 sync = lock.sync; 717 } 718 719 /** 720 * Acquires the read lock. 721 * 722 * <p>Acquires the read lock if the write lock is not held by 723 * another thread and returns immediately. 724 * 725 * <p>If the write lock is held by another thread then 726 * the current thread becomes disabled for thread scheduling 727 * purposes and lies dormant until the read lock has been acquired. 728 */ 729 public void lock() { 730 sync.acquireShared(1); 731 } 732 733 /** 734 * Acquires the read lock unless the current thread is 735 * {@linkplain Thread#interrupt interrupted}. 736 * 737 * <p>Acquires the read lock if the write lock is not held 738 * by another thread and returns immediately. 739 * 740 * <p>If the write lock is held by another thread then the 741 * current thread becomes disabled for thread scheduling 742 * purposes and lies dormant until one of two things happens: 743 * 744 * <ul> 745 * 746 * <li>The read lock is acquired by the current thread; or 747 * 748 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 749 * the current thread. 750 * 751 * </ul> 752 * 753 * <p>If the current thread: 754 * 755 * <ul> 756 * 757 * <li>has its interrupted status set on entry to this method; or 758 * 759 * <li>is {@linkplain Thread#interrupt interrupted} while 760 * acquiring the read lock, 761 * 762 * </ul> 763 * 764 * then {@link InterruptedException} is thrown and the current 765 * thread's interrupted status is cleared. 766 * 767 * <p>In this implementation, as this method is an explicit 768 * interruption point, preference is given to responding to 769 * the interrupt over normal or reentrant acquisition of the 770 * lock. 771 * 772 * @throws InterruptedException if the current thread is interrupted 773 */ 774 public void lockInterruptibly() throws InterruptedException { 775 sync.acquireSharedInterruptibly(1); 776 } 777 778 /** 779 * Acquires the read lock only if the write lock is not held by 780 * another thread at the time of invocation. 781 * 782 * <p>Acquires the read lock if the write lock is not held by 783 * another thread and returns immediately with the value 784 * {@code true}. Even when this lock has been set to use a 785 * fair ordering policy, a call to {@code tryLock()} 786 * <em>will</em> immediately acquire the read lock if it is 787 * available, whether or not other threads are currently 788 * waiting for the read lock. This "barging" behavior 789 * can be useful in certain circumstances, even though it 790 * breaks fairness. If you want to honor the fairness setting 791 * for this lock, then use {@link #tryLock(long, TimeUnit) 792 * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent 793 * (it also detects interruption). 794 * 795 * <p>If the write lock is held by another thread then 796 * this method will return immediately with the value 797 * {@code false}. 798 * 799 * @return {@code true} if the read lock was acquired 800 */ 801 public boolean tryLock() { 802 return sync.tryReadLock(); 803 } 804 805 /** 806 * Acquires the read lock if the write lock is not held by 807 * another thread within the given waiting time and the 808 * current thread has not been {@linkplain Thread#interrupt 809 * interrupted}. 810 * 811 * <p>Acquires the read lock if the write lock is not held by 812 * another thread and returns immediately with the value 813 * {@code true}. If this lock has been set to use a fair 814 * ordering policy then an available lock <em>will not</em> be 815 * acquired if any other threads are waiting for the 816 * lock. This is in contrast to the {@link #tryLock()} 817 * method. If you want a timed {@code tryLock} that does 818 * permit barging on a fair lock then combine the timed and 819 * un-timed forms together: 820 * 821 * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... } 822 * </pre> 823 * 824 * <p>If the write lock is held by another thread then the 825 * current thread becomes disabled for thread scheduling 826 * purposes and lies dormant until one of three things happens: 827 * 828 * <ul> 829 * 830 * <li>The read lock is acquired by the current thread; or 831 * 832 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 833 * the current thread; or 834 * 835 * <li>The specified waiting time elapses. 836 * 837 * </ul> 838 * 839 * <p>If the read lock is acquired then the value {@code true} is 840 * returned. 841 * 842 * <p>If the current thread: 843 * 844 * <ul> 845 * 846 * <li>has its interrupted status set on entry to this method; or 847 * 848 * <li>is {@linkplain Thread#interrupt interrupted} while 849 * acquiring the read lock, 850 * 851 * </ul> then {@link InterruptedException} is thrown and the 852 * current thread's interrupted status is cleared. 853 * 854 * <p>If the specified waiting time elapses then the value 855 * {@code false} is returned. If the time is less than or 856 * equal to zero, the method will not wait at all. 857 * 858 * <p>In this implementation, as this method is an explicit 859 * interruption point, preference is given to responding to 860 * the interrupt over normal or reentrant acquisition of the 861 * lock, and over reporting the elapse of the waiting time. 862 * 863 * @param timeout the time to wait for the read lock 864 * @param unit the time unit of the timeout argument 865 * @return {@code true} if the read lock was acquired 866 * @throws InterruptedException if the current thread is interrupted 867 * @throws NullPointerException if the time unit is null 868 * 869 */ 870 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { 871 return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); 872 } 873 874 /** 875 * Attempts to release this lock. 876 * 877 * <p> If the number of readers is now zero then the lock 878 * is made available for write lock attempts. 879 */ 880 public void unlock() { 881 sync.releaseShared(1); 882 } 883 884 /** 885 * Throws {@code UnsupportedOperationException} because 886 * {@code ReadLocks} do not support conditions. 887 * 888 * @throws UnsupportedOperationException always 889 */ 890 public Condition newCondition() { 891 throw new UnsupportedOperationException(); 892 } 893 894 /** 895 * Returns a string identifying this lock, as well as its lock state. 896 * The state, in brackets, includes the String {@code "Read locks ="} 897 * followed by the number of held read locks. 898 * 899 * @return a string identifying this lock, as well as its lock state 900 */ 901 public String toString() { 902 int r = sync.getReadLockCount(); 903 return super.toString() + 904 "[Read locks = " + r + "]"; 905 } 906 } 907 908 /** 909 * The lock returned by method {@link ReentrantReadWriteLock#writeLock}. 910 */ 911 public static class WriteLock implements Lock, java.io.Serializable { 912 private static final long serialVersionUID = -4992448646407690164L; 913 private final Sync sync; 914 915 /** 916 * Constructor for use by subclasses 917 * 918 * @param lock the outer lock object 919 * @throws NullPointerException if the lock is null 920 */ 921 protected WriteLock(ReentrantReadWriteLock lock) { 922 sync = lock.sync; 923 } 924 925 /** 926 * Acquires the write lock. 927 * 928 * <p>Acquires the write lock if neither the read nor write lock 929 * are held by another thread 930 * and returns immediately, setting the write lock hold count to 931 * one. 932 * 933 * <p>If the current thread already holds the write lock then the 934 * hold count is incremented by one and the method returns 935 * immediately. 936 * 937 * <p>If the lock is held by another thread then the current 938 * thread becomes disabled for thread scheduling purposes and 939 * lies dormant until the write lock has been acquired, at which 940 * time the write lock hold count is set to one. 941 */ 942 public void lock() { 943 sync.acquire(1); 944 } 945 946 /** 947 * Acquires the write lock unless the current thread is 948 * {@linkplain Thread#interrupt interrupted}. 949 * 950 * <p>Acquires the write lock if neither the read nor write lock 951 * are held by another thread 952 * and returns immediately, setting the write lock hold count to 953 * one. 954 * 955 * <p>If the current thread already holds this lock then the 956 * hold count is incremented by one and the method returns 957 * immediately. 958 * 959 * <p>If the lock is held by another thread then the current 960 * thread becomes disabled for thread scheduling purposes and 961 * lies dormant until one of two things happens: 962 * 963 * <ul> 964 * 965 * <li>The write lock is acquired by the current thread; or 966 * 967 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 968 * the current thread. 969 * 970 * </ul> 971 * 972 * <p>If the write lock is acquired by the current thread then the 973 * lock hold count is set to one. 974 * 975 * <p>If the current thread: 976 * 977 * <ul> 978 * 979 * <li>has its interrupted status set on entry to this method; 980 * or 981 * 982 * <li>is {@linkplain Thread#interrupt interrupted} while 983 * acquiring the write lock, 984 * 985 * </ul> 986 * 987 * then {@link InterruptedException} is thrown and the current 988 * thread's interrupted status is cleared. 989 * 990 * <p>In this implementation, as this method is an explicit 991 * interruption point, preference is given to responding to 992 * the interrupt over normal or reentrant acquisition of the 993 * lock. 994 * 995 * @throws InterruptedException if the current thread is interrupted 996 */ 997 public void lockInterruptibly() throws InterruptedException { 998 sync.acquireInterruptibly(1); 999 } 1000 1001 /** 1002 * Acquires the write lock only if it is not held by another thread 1003 * at the time of invocation. 1004 * 1005 * <p>Acquires the write lock if neither the read nor write lock 1006 * are held by another thread 1007 * and returns immediately with the value {@code true}, 1008 * setting the write lock hold count to one. Even when this lock has 1009 * been set to use a fair ordering policy, a call to 1010 * {@code tryLock()} <em>will</em> immediately acquire the 1011 * lock if it is available, whether or not other threads are 1012 * currently waiting for the write lock. This "barging" 1013 * behavior can be useful in certain circumstances, even 1014 * though it breaks fairness. If you want to honor the 1015 * fairness setting for this lock, then use {@link 1016 * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } 1017 * which is almost equivalent (it also detects interruption). 1018 * 1019 * <p> If the current thread already holds this lock then the 1020 * hold count is incremented by one and the method returns 1021 * {@code true}. 1022 * 1023 * <p>If the lock is held by another thread then this method 1024 * will return immediately with the value {@code false}. 1025 * 1026 * @return {@code true} if the lock was free and was acquired 1027 * by the current thread, or the write lock was already held 1028 * by the current thread; and {@code false} otherwise. 1029 */ 1030 public boolean tryLock( ) { 1031 return sync.tryWriteLock(); 1032 } 1033 1034 /** 1035 * Acquires the write lock if it is not held by another thread 1036 * within the given waiting time and the current thread has 1037 * not been {@linkplain Thread#interrupt interrupted}. 1038 * 1039 * <p>Acquires the write lock if neither the read nor write lock 1040 * are held by another thread 1041 * and returns immediately with the value {@code true}, 1042 * setting the write lock hold count to one. If this lock has been 1043 * set to use a fair ordering policy then an available lock 1044 * <em>will not</em> be acquired if any other threads are 1045 * waiting for the write lock. This is in contrast to the {@link 1046 * #tryLock()} method. If you want a timed {@code tryLock} 1047 * that does permit barging on a fair lock then combine the 1048 * timed and un-timed forms together: 1049 * 1050 * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... } 1051 * </pre> 1052 * 1053 * <p>If the current thread already holds this lock then the 1054 * hold count is incremented by one and the method returns 1055 * {@code true}. 1056 * 1057 * <p>If the lock is held by another thread then the current 1058 * thread becomes disabled for thread scheduling purposes and 1059 * lies dormant until one of three things happens: 1060 * 1061 * <ul> 1062 * 1063 * <li>The write lock is acquired by the current thread; or 1064 * 1065 * <li>Some other thread {@linkplain Thread#interrupt interrupts} 1066 * the current thread; or 1067 * 1068 * <li>The specified waiting time elapses 1069 * 1070 * </ul> 1071 * 1072 * <p>If the write lock is acquired then the value {@code true} is 1073 * returned and the write lock hold count is set to one. 1074 * 1075 * <p>If the current thread: 1076 * 1077 * <ul> 1078 * 1079 * <li>has its interrupted status set on entry to this method; 1080 * or 1081 * 1082 * <li>is {@linkplain Thread#interrupt interrupted} while 1083 * acquiring the write lock, 1084 * 1085 * </ul> 1086 * 1087 * then {@link InterruptedException} is thrown and the current 1088 * thread's interrupted status is cleared. 1089 * 1090 * <p>If the specified waiting time elapses then the value 1091 * {@code false} is returned. If the time is less than or 1092 * equal to zero, the method will not wait at all. 1093 * 1094 * <p>In this implementation, as this method is an explicit 1095 * interruption point, preference is given to responding to 1096 * the interrupt over normal or reentrant acquisition of the 1097 * lock, and over reporting the elapse of the waiting time. 1098 * 1099 * @param timeout the time to wait for the write lock 1100 * @param unit the time unit of the timeout argument 1101 * 1102 * @return {@code true} if the lock was free and was acquired 1103 * by the current thread, or the write lock was already held by the 1104 * current thread; and {@code false} if the waiting time 1105 * elapsed before the lock could be acquired. 1106 * 1107 * @throws InterruptedException if the current thread is interrupted 1108 * @throws NullPointerException if the time unit is null 1109 * 1110 */ 1111 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { 1112 return sync.tryAcquireNanos(1, unit.toNanos(timeout)); 1113 } 1114 1115 /** 1116 * Attempts to release this lock. 1117 * 1118 * <p>If the current thread is the holder of this lock then 1119 * the hold count is decremented. If the hold count is now 1120 * zero then the lock is released. If the current thread is 1121 * not the holder of this lock then {@link 1122 * IllegalMonitorStateException} is thrown. 1123 * 1124 * @throws IllegalMonitorStateException if the current thread does not 1125 * hold this lock. 1126 */ 1127 public void unlock() { 1128 sync.release(1); 1129 } 1130 1131 /** 1132 * Returns a {@link Condition} instance for use with this 1133 * {@link Lock} instance. 1134 * <p>The returned {@link Condition} instance supports the same 1135 * usages as do the {@link Object} monitor methods ({@link 1136 * Object#wait() wait}, {@link Object#notify notify}, and {@link 1137 * Object#notifyAll notifyAll}) when used with the built-in 1138 * monitor lock. 1139 * 1140 * <ul> 1141 * 1142 * <li>If this write lock is not held when any {@link 1143 * Condition} method is called then an {@link 1144 * IllegalMonitorStateException} is thrown. (Read locks are 1145 * held independently of write locks, so are not checked or 1146 * affected. However it is essentially always an error to 1147 * invoke a condition waiting method when the current thread 1148 * has also acquired read locks, since other threads that 1149 * could unblock it will not be able to acquire the write 1150 * lock.) 1151 * 1152 * <li>When the condition {@linkplain Condition#await() waiting} 1153 * methods are called the write lock is released and, before 1154 * they return, the write lock is reacquired and the lock hold 1155 * count restored to what it was when the method was called. 1156 * 1157 * <li>If a thread is {@linkplain Thread#interrupt interrupted} while 1158 * waiting then the wait will terminate, an {@link 1159 * InterruptedException} will be thrown, and the thread's 1160 * interrupted status will be cleared. 1161 * 1162 * <li> Waiting threads are signalled in FIFO order. 1163 * 1164 * <li>The ordering of lock reacquisition for threads returning 1165 * from waiting methods is the same as for threads initially 1166 * acquiring the lock, which is in the default case not specified, 1167 * but for <em>fair</em> locks favors those threads that have been 1168 * waiting the longest. 1169 * 1170 * </ul> 1171 * 1172 * @return the Condition object 1173 */ 1174 public Condition newCondition() { 1175 return sync.newCondition(); 1176 } 1177 1178 /** 1179 * Returns a string identifying this lock, as well as its lock 1180 * state. The state, in brackets includes either the String 1181 * {@code "Unlocked"} or the String {@code "Locked by"} 1182 * followed by the {@linkplain Thread#getName name} of the owning thread. 1183 * 1184 * @return a string identifying this lock, as well as its lock state 1185 */ 1186 public String toString() { 1187 Thread o = sync.getOwner(); 1188 return super.toString() + ((o == null) ? 1189 "[Unlocked]" : 1190 "[Locked by thread " + o.getName() + "]"); 1191 } 1192 1193 /** 1194 * Queries if this write lock is held by the current thread. 1195 * Identical in effect to {@link 1196 * ReentrantReadWriteLock#isWriteLockedByCurrentThread}. 1197 * 1198 * @return {@code true} if the current thread holds this lock and 1199 * {@code false} otherwise 1200 * @since 1.6 1201 */ 1202 public boolean isHeldByCurrentThread() { 1203 return sync.isHeldExclusively(); 1204 } 1205 1206 /** 1207 * Queries the number of holds on this write lock by the current 1208 * thread. A thread has a hold on a lock for each lock action 1209 * that is not matched by an unlock action. Identical in effect 1210 * to {@link ReentrantReadWriteLock#getWriteHoldCount}. 1211 * 1212 * @return the number of holds on this lock by the current thread, 1213 * or zero if this lock is not held by the current thread 1214 * @since 1.6 1215 */ 1216 public int getHoldCount() { 1217 return sync.getWriteHoldCount(); 1218 } 1219 } 1220 1221 // Instrumentation and status 1222 1223 /** 1224 * Returns {@code true} if this lock has fairness set true. 1225 * 1226 * @return {@code true} if this lock has fairness set true 1227 */ 1228 public final boolean isFair() { 1229 return sync instanceof FairSync; 1230 } 1231 1232 /** 1233 * Returns the thread that currently owns the write lock, or 1234 * {@code null} if not owned. When this method is called by a 1235 * thread that is not the owner, the return value reflects a 1236 * best-effort approximation of current lock status. For example, 1237 * the owner may be momentarily {@code null} even if there are 1238 * threads trying to acquire the lock but have not yet done so. 1239 * This method is designed to facilitate construction of 1240 * subclasses that provide more extensive lock monitoring 1241 * facilities. 1242 * 1243 * @return the owner, or {@code null} if not owned 1244 */ 1245 protected Thread getOwner() { 1246 return sync.getOwner(); 1247 } 1248 1249 /** 1250 * Queries the number of read locks held for this lock. This 1251 * method is designed for use in monitoring system state, not for 1252 * synchronization control. 1253 * @return the number of read locks held. 1254 */ 1255 public int getReadLockCount() { 1256 return sync.getReadLockCount(); 1257 } 1258 1259 /** 1260 * Queries if the write lock is held by any thread. This method is 1261 * designed for use in monitoring system state, not for 1262 * synchronization control. 1263 * 1264 * @return {@code true} if any thread holds the write lock and 1265 * {@code false} otherwise 1266 */ 1267 public boolean isWriteLocked() { 1268 return sync.isWriteLocked(); 1269 } 1270 1271 /** 1272 * Queries if the write lock is held by the current thread. 1273 * 1274 * @return {@code true} if the current thread holds the write lock and 1275 * {@code false} otherwise 1276 */ 1277 public boolean isWriteLockedByCurrentThread() { 1278 return sync.isHeldExclusively(); 1279 } 1280 1281 /** 1282 * Queries the number of reentrant write holds on this lock by the 1283 * current thread. A writer thread has a hold on a lock for 1284 * each lock action that is not matched by an unlock action. 1285 * 1286 * @return the number of holds on the write lock by the current thread, 1287 * or zero if the write lock is not held by the current thread 1288 */ 1289 public int getWriteHoldCount() { 1290 return sync.getWriteHoldCount(); 1291 } 1292 1293 /** 1294 * Queries the number of reentrant read holds on this lock by the 1295 * current thread. A reader thread has a hold on a lock for 1296 * each lock action that is not matched by an unlock action. 1297 * 1298 * @return the number of holds on the read lock by the current thread, 1299 * or zero if the read lock is not held by the current thread 1300 * @since 1.6 1301 */ 1302 public int getReadHoldCount() { 1303 return sync.getReadHoldCount(); 1304 } 1305 1306 /** 1307 * Returns a collection containing threads that may be waiting to 1308 * acquire the write lock. Because the actual set of threads may 1309 * change dynamically while constructing this result, the returned 1310 * collection is only a best-effort estimate. The elements of the 1311 * returned collection are in no particular order. This method is 1312 * designed to facilitate construction of subclasses that provide 1313 * more extensive lock monitoring facilities. 1314 * 1315 * @return the collection of threads 1316 */ 1317 protected Collection<Thread> getQueuedWriterThreads() { 1318 return sync.getExclusiveQueuedThreads(); 1319 } 1320 1321 /** 1322 * Returns a collection containing threads that may be waiting to 1323 * acquire the read lock. Because the actual set of threads may 1324 * change dynamically while constructing this result, the returned 1325 * collection is only a best-effort estimate. The elements of the 1326 * returned collection are in no particular order. This method is 1327 * designed to facilitate construction of subclasses that provide 1328 * more extensive lock monitoring facilities. 1329 * 1330 * @return the collection of threads 1331 */ 1332 protected Collection<Thread> getQueuedReaderThreads() { 1333 return sync.getSharedQueuedThreads(); 1334 } 1335 1336 /** 1337 * Queries whether any threads are waiting to acquire the read or 1338 * write lock. Note that because cancellations may occur at any 1339 * time, a {@code true} return does not guarantee that any other 1340 * thread will ever acquire a lock. This method is designed 1341 * primarily for use in monitoring of the system state. 1342 * 1343 * @return {@code true} if there may be other threads waiting to 1344 * acquire the lock 1345 */ 1346 public final boolean hasQueuedThreads() { 1347 return sync.hasQueuedThreads(); 1348 } 1349 1350 /** 1351 * Queries whether the given thread is waiting to acquire either 1352 * the read or write lock. Note that because cancellations may 1353 * occur at any time, a {@code true} return does not guarantee 1354 * that this thread will ever acquire a lock. This method is 1355 * designed primarily for use in monitoring of the system state. 1356 * 1357 * @param thread the thread 1358 * @return {@code true} if the given thread is queued waiting for this lock 1359 * @throws NullPointerException if the thread is null 1360 */ 1361 public final boolean hasQueuedThread(Thread thread) { 1362 return sync.isQueued(thread); 1363 } 1364 1365 /** 1366 * Returns an estimate of the number of threads waiting to acquire 1367 * either the read or write lock. The value is only an estimate 1368 * because the number of threads may change dynamically while this 1369 * method traverses internal data structures. This method is 1370 * designed for use in monitoring of the system state, not for 1371 * synchronization control. 1372 * 1373 * @return the estimated number of threads waiting for this lock 1374 */ 1375 public final int getQueueLength() { 1376 return sync.getQueueLength(); 1377 } 1378 1379 /** 1380 * Returns a collection containing threads that may be waiting to 1381 * acquire either the read or write lock. Because the actual set 1382 * of threads may change dynamically while constructing this 1383 * result, the returned collection is only a best-effort estimate. 1384 * The elements of the returned collection are in no particular 1385 * order. This method is designed to facilitate construction of 1386 * subclasses that provide more extensive monitoring facilities. 1387 * 1388 * @return the collection of threads 1389 */ 1390 protected Collection<Thread> getQueuedThreads() { 1391 return sync.getQueuedThreads(); 1392 } 1393 1394 /** 1395 * Queries whether any threads are waiting on the given condition 1396 * associated with the write lock. Note that because timeouts and 1397 * interrupts may occur at any time, a {@code true} return does 1398 * not guarantee that a future {@code signal} will awaken any 1399 * threads. This method is designed primarily for use in 1400 * monitoring of the system state. 1401 * 1402 * @param condition the condition 1403 * @return {@code true} if there are any waiting threads 1404 * @throws IllegalMonitorStateException if this lock is not held 1405 * @throws IllegalArgumentException if the given condition is 1406 * not associated with this lock 1407 * @throws NullPointerException if the condition is null 1408 */ 1409 public boolean hasWaiters(Condition condition) { 1410 if (condition == null) 1411 throw new NullPointerException(); 1412 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 1413 throw new IllegalArgumentException("not owner"); 1414 return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); 1415 } 1416 1417 /** 1418 * Returns an estimate of the number of threads waiting on the 1419 * given condition associated with the write lock. Note that because 1420 * timeouts and interrupts may occur at any time, the estimate 1421 * serves only as an upper bound on the actual number of waiters. 1422 * This method is designed for use in monitoring of the system 1423 * state, not for synchronization control. 1424 * 1425 * @param condition the condition 1426 * @return the estimated number of waiting threads 1427 * @throws IllegalMonitorStateException if this lock is not held 1428 * @throws IllegalArgumentException if the given condition is 1429 * not associated with this lock 1430 * @throws NullPointerException if the condition is null 1431 */ 1432 public int getWaitQueueLength(Condition condition) { 1433 if (condition == null) 1434 throw new NullPointerException(); 1435 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 1436 throw new IllegalArgumentException("not owner"); 1437 return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); 1438 } 1439 1440 /** 1441 * Returns a collection containing those threads that may be 1442 * waiting on the given condition associated with the write lock. 1443 * Because the actual set of threads may change dynamically while 1444 * constructing this result, the returned collection is only a 1445 * best-effort estimate. The elements of the returned collection 1446 * are in no particular order. This method is designed to 1447 * facilitate construction of subclasses that provide more 1448 * extensive condition monitoring facilities. 1449 * 1450 * @param condition the condition 1451 * @return the collection of threads 1452 * @throws IllegalMonitorStateException if this lock is not held 1453 * @throws IllegalArgumentException if the given condition is 1454 * not associated with this lock 1455 * @throws NullPointerException if the condition is null 1456 */ 1457 protected Collection<Thread> getWaitingThreads(Condition condition) { 1458 if (condition == null) 1459 throw new NullPointerException(); 1460 if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) 1461 throw new IllegalArgumentException("not owner"); 1462 return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); 1463 } 1464 1465 /** 1466 * Returns a string identifying this lock, as well as its lock state. 1467 * The state, in brackets, includes the String {@code "Write locks ="} 1468 * followed by the number of reentrantly held write locks, and the 1469 * String {@code "Read locks ="} followed by the number of held 1470 * read locks. 1471 * 1472 * @return a string identifying this lock, as well as its lock state 1473 */ 1474 public String toString() { 1475 int c = sync.getCount(); 1476 int w = Sync.exclusiveCount(c); 1477 int r = Sync.sharedCount(c); 1478 1479 return super.toString() + 1480 "[Write locks = " + w + ", Read locks = " + r + "]"; 1481 } 1482 1483 }