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