rt/emul/compact/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java Sat Mar 19 10:46:31 2016 +0100
1.3 @@ -0,0 +1,1486 @@
1.4 +/*
1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.6 + *
1.7 + * This code is free software; you can redistribute it and/or modify it
1.8 + * under the terms of the GNU General Public License version 2 only, as
1.9 + * published by the Free Software Foundation. Oracle designates this
1.10 + * particular file as subject to the "Classpath" exception as provided
1.11 + * by Oracle in the LICENSE file that accompanied this code.
1.12 + *
1.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.16 + * version 2 for more details (a copy is included in the LICENSE file that
1.17 + * accompanied this code).
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License version
1.20 + * 2 along with this work; if not, write to the Free Software Foundation,
1.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.22 + *
1.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.24 + * or visit www.oracle.com if you need additional information or have any
1.25 + * questions.
1.26 + */
1.27 +
1.28 +/*
1.29 + * This file is available under and governed by the GNU General Public
1.30 + * License version 2 only, as published by the Free Software Foundation.
1.31 + * However, the following notice accompanied the original version of this
1.32 + * file:
1.33 + *
1.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
1.35 + * Expert Group and released to the public domain, as explained at
1.36 + * http://creativecommons.org/publicdomain/zero/1.0/
1.37 + */
1.38 +
1.39 +package java.util.concurrent.locks;
1.40 +import java.util.concurrent.*;
1.41 +import java.util.concurrent.atomic.*;
1.42 +import java.util.*;
1.43 +
1.44 +/**
1.45 + * An implementation of {@link ReadWriteLock} supporting similar
1.46 + * semantics to {@link ReentrantLock}.
1.47 + * <p>This class has the following properties:
1.48 + *
1.49 + * <ul>
1.50 + * <li><b>Acquisition order</b>
1.51 + *
1.52 + * <p> This class does not impose a reader or writer preference
1.53 + * ordering for lock access. However, it does support an optional
1.54 + * <em>fairness</em> policy.
1.55 + *
1.56 + * <dl>
1.57 + * <dt><b><i>Non-fair mode (default)</i></b>
1.58 + * <dd>When constructed as non-fair (the default), the order of entry
1.59 + * to the read and write lock is unspecified, subject to reentrancy
1.60 + * constraints. A nonfair lock that is continuously contended may
1.61 + * indefinitely postpone one or more reader or writer threads, but
1.62 + * will normally have higher throughput than a fair lock.
1.63 + * <p>
1.64 + *
1.65 + * <dt><b><i>Fair mode</i></b>
1.66 + * <dd> When constructed as fair, threads contend for entry using an
1.67 + * approximately arrival-order policy. When the currently held lock
1.68 + * is released either the longest-waiting single writer thread will
1.69 + * be assigned the write lock, or if there is a group of reader threads
1.70 + * waiting longer than all waiting writer threads, that group will be
1.71 + * assigned the read lock.
1.72 + *
1.73 + * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
1.74 + * will block if either the write lock is held, or there is a waiting
1.75 + * writer thread. The thread will not acquire the read lock until
1.76 + * after the oldest currently waiting writer thread has acquired and
1.77 + * released the write lock. Of course, if a waiting writer abandons
1.78 + * its wait, leaving one or more reader threads as the longest waiters
1.79 + * in the queue with the write lock free, then those readers will be
1.80 + * assigned the read lock.
1.81 + *
1.82 + * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
1.83 + * will block unless both the read lock and write lock are free (which
1.84 + * implies there are no waiting threads). (Note that the non-blocking
1.85 + * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
1.86 + * do not honor this fair setting and will acquire the lock if it is
1.87 + * possible, regardless of waiting threads.)
1.88 + * <p>
1.89 + * </dl>
1.90 + *
1.91 + * <li><b>Reentrancy</b>
1.92 + *
1.93 + * <p>This lock allows both readers and writers to reacquire read or
1.94 + * write locks in the style of a {@link ReentrantLock}. Non-reentrant
1.95 + * readers are not allowed until all write locks held by the writing
1.96 + * thread have been released.
1.97 + *
1.98 + * <p>Additionally, a writer can acquire the read lock, but not
1.99 + * vice-versa. Among other applications, reentrancy can be useful
1.100 + * when write locks are held during calls or callbacks to methods that
1.101 + * perform reads under read locks. If a reader tries to acquire the
1.102 + * write lock it will never succeed.
1.103 + *
1.104 + * <li><b>Lock downgrading</b>
1.105 + * <p>Reentrancy also allows downgrading from the write lock to a read lock,
1.106 + * by acquiring the write lock, then the read lock and then releasing the
1.107 + * write lock. However, upgrading from a read lock to the write lock is
1.108 + * <b>not</b> possible.
1.109 + *
1.110 + * <li><b>Interruption of lock acquisition</b>
1.111 + * <p>The read lock and write lock both support interruption during lock
1.112 + * acquisition.
1.113 + *
1.114 + * <li><b>{@link Condition} support</b>
1.115 + * <p>The write lock provides a {@link Condition} implementation that
1.116 + * behaves in the same way, with respect to the write lock, as the
1.117 + * {@link Condition} implementation provided by
1.118 + * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
1.119 + * This {@link Condition} can, of course, only be used with the write lock.
1.120 + *
1.121 + * <p>The read lock does not support a {@link Condition} and
1.122 + * {@code readLock().newCondition()} throws
1.123 + * {@code UnsupportedOperationException}.
1.124 + *
1.125 + * <li><b>Instrumentation</b>
1.126 + * <p>This class supports methods to determine whether locks
1.127 + * are held or contended. These methods are designed for monitoring
1.128 + * system state, not for synchronization control.
1.129 + * </ul>
1.130 + *
1.131 + * <p>Serialization of this class behaves in the same way as built-in
1.132 + * locks: a deserialized lock is in the unlocked state, regardless of
1.133 + * its state when serialized.
1.134 + *
1.135 + * <p><b>Sample usages</b>. Here is a code sketch showing how to perform
1.136 + * lock downgrading after updating a cache (exception handling is
1.137 + * particularly tricky when handling multiple locks in a non-nested
1.138 + * fashion):
1.139 + *
1.140 + * <pre> {@code
1.141 + * class CachedData {
1.142 + * Object data;
1.143 + * volatile boolean cacheValid;
1.144 + * final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
1.145 + *
1.146 + * void processCachedData() {
1.147 + * rwl.readLock().lock();
1.148 + * if (!cacheValid) {
1.149 + * // Must release read lock before acquiring write lock
1.150 + * rwl.readLock().unlock();
1.151 + * rwl.writeLock().lock();
1.152 + * try {
1.153 + * // Recheck state because another thread might have
1.154 + * // acquired write lock and changed state before we did.
1.155 + * if (!cacheValid) {
1.156 + * data = ...
1.157 + * cacheValid = true;
1.158 + * }
1.159 + * // Downgrade by acquiring read lock before releasing write lock
1.160 + * rwl.readLock().lock();
1.161 + * } finally {
1.162 + * rwl.writeLock().unlock(); // Unlock write, still hold read
1.163 + * }
1.164 + * }
1.165 + *
1.166 + * try {
1.167 + * use(data);
1.168 + * } finally {
1.169 + * rwl.readLock().unlock();
1.170 + * }
1.171 + * }
1.172 + * }}</pre>
1.173 + *
1.174 + * ReentrantReadWriteLocks can be used to improve concurrency in some
1.175 + * uses of some kinds of Collections. This is typically worthwhile
1.176 + * only when the collections are expected to be large, accessed by
1.177 + * more reader threads than writer threads, and entail operations with
1.178 + * overhead that outweighs synchronization overhead. For example, here
1.179 + * is a class using a TreeMap that is expected to be large and
1.180 + * concurrently accessed.
1.181 + *
1.182 + * <pre>{@code
1.183 + * class RWDictionary {
1.184 + * private final Map<String, Data> m = new TreeMap<String, Data>();
1.185 + * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
1.186 + * private final Lock r = rwl.readLock();
1.187 + * private final Lock w = rwl.writeLock();
1.188 + *
1.189 + * public Data get(String key) {
1.190 + * r.lock();
1.191 + * try { return m.get(key); }
1.192 + * finally { r.unlock(); }
1.193 + * }
1.194 + * public String[] allKeys() {
1.195 + * r.lock();
1.196 + * try { return m.keySet().toArray(); }
1.197 + * finally { r.unlock(); }
1.198 + * }
1.199 + * public Data put(String key, Data value) {
1.200 + * w.lock();
1.201 + * try { return m.put(key, value); }
1.202 + * finally { w.unlock(); }
1.203 + * }
1.204 + * public void clear() {
1.205 + * w.lock();
1.206 + * try { m.clear(); }
1.207 + * finally { w.unlock(); }
1.208 + * }
1.209 + * }}</pre>
1.210 + *
1.211 + * <h3>Implementation Notes</h3>
1.212 + *
1.213 + * <p>This lock supports a maximum of 65535 recursive write locks
1.214 + * and 65535 read locks. Attempts to exceed these limits result in
1.215 + * {@link Error} throws from locking methods.
1.216 + *
1.217 + * @since 1.5
1.218 + * @author Doug Lea
1.219 + *
1.220 + */
1.221 +public class ReentrantReadWriteLock
1.222 + implements ReadWriteLock, java.io.Serializable {
1.223 + private static final long serialVersionUID = -6992448646407690164L;
1.224 + /** Inner class providing readlock */
1.225 + private final ReentrantReadWriteLock.ReadLock readerLock;
1.226 + /** Inner class providing writelock */
1.227 + private final ReentrantReadWriteLock.WriteLock writerLock;
1.228 + /** Performs all synchronization mechanics */
1.229 + final Sync sync;
1.230 +
1.231 + /**
1.232 + * Creates a new {@code ReentrantReadWriteLock} with
1.233 + * default (nonfair) ordering properties.
1.234 + */
1.235 + public ReentrantReadWriteLock() {
1.236 + this(false);
1.237 + }
1.238 +
1.239 + /**
1.240 + * Creates a new {@code ReentrantReadWriteLock} with
1.241 + * the given fairness policy.
1.242 + *
1.243 + * @param fair {@code true} if this lock should use a fair ordering policy
1.244 + */
1.245 + public ReentrantReadWriteLock(boolean fair) {
1.246 + sync = fair ? new FairSync() : new NonfairSync();
1.247 + readerLock = new ReadLock(this);
1.248 + writerLock = new WriteLock(this);
1.249 + }
1.250 +
1.251 + public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
1.252 + public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
1.253 +
1.254 + /**
1.255 + * Synchronization implementation for ReentrantReadWriteLock.
1.256 + * Subclassed into fair and nonfair versions.
1.257 + */
1.258 + abstract static class Sync extends AbstractQueuedSynchronizer {
1.259 + private static final long serialVersionUID = 6317671515068378041L;
1.260 +
1.261 + /*
1.262 + * Read vs write count extraction constants and functions.
1.263 + * Lock state is logically divided into two unsigned shorts:
1.264 + * The lower one representing the exclusive (writer) lock hold count,
1.265 + * and the upper the shared (reader) hold count.
1.266 + */
1.267 +
1.268 + static final int SHARED_SHIFT = 16;
1.269 + static final int SHARED_UNIT = (1 << SHARED_SHIFT);
1.270 + static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
1.271 + static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
1.272 +
1.273 + /** Returns the number of shared holds represented in count */
1.274 + static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
1.275 + /** Returns the number of exclusive holds represented in count */
1.276 + static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
1.277 +
1.278 + /**
1.279 + * A counter for per-thread read hold counts.
1.280 + * Maintained as a ThreadLocal; cached in cachedHoldCounter
1.281 + */
1.282 + static final class HoldCounter {
1.283 + int count = 0;
1.284 + // Use id, not reference, to avoid garbage retention
1.285 + final long tid = Thread.currentThread().getId();
1.286 + }
1.287 +
1.288 + /**
1.289 + * ThreadLocal subclass. Easiest to explicitly define for sake
1.290 + * of deserialization mechanics.
1.291 + */
1.292 + static final class ThreadLocalHoldCounter
1.293 + extends ThreadLocal<HoldCounter> {
1.294 + public HoldCounter initialValue() {
1.295 + return new HoldCounter();
1.296 + }
1.297 + }
1.298 +
1.299 + /**
1.300 + * The number of reentrant read locks held by current thread.
1.301 + * Initialized only in constructor and readObject.
1.302 + * Removed whenever a thread's read hold count drops to 0.
1.303 + */
1.304 + private transient ThreadLocalHoldCounter readHolds;
1.305 +
1.306 + /**
1.307 + * The hold count of the last thread to successfully acquire
1.308 + * readLock. This saves ThreadLocal lookup in the common case
1.309 + * where the next thread to release is the last one to
1.310 + * acquire. This is non-volatile since it is just used
1.311 + * as a heuristic, and would be great for threads to cache.
1.312 + *
1.313 + * <p>Can outlive the Thread for which it is caching the read
1.314 + * hold count, but avoids garbage retention by not retaining a
1.315 + * reference to the Thread.
1.316 + *
1.317 + * <p>Accessed via a benign data race; relies on the memory
1.318 + * model's final field and out-of-thin-air guarantees.
1.319 + */
1.320 + private transient HoldCounter cachedHoldCounter;
1.321 +
1.322 + /**
1.323 + * firstReader is the first thread to have acquired the read lock.
1.324 + * firstReaderHoldCount is firstReader's hold count.
1.325 + *
1.326 + * <p>More precisely, firstReader is the unique thread that last
1.327 + * changed the shared count from 0 to 1, and has not released the
1.328 + * read lock since then; null if there is no such thread.
1.329 + *
1.330 + * <p>Cannot cause garbage retention unless the thread terminated
1.331 + * without relinquishing its read locks, since tryReleaseShared
1.332 + * sets it to null.
1.333 + *
1.334 + * <p>Accessed via a benign data race; relies on the memory
1.335 + * model's out-of-thin-air guarantees for references.
1.336 + *
1.337 + * <p>This allows tracking of read holds for uncontended read
1.338 + * locks to be very cheap.
1.339 + */
1.340 + private transient Thread firstReader = null;
1.341 + private transient int firstReaderHoldCount;
1.342 +
1.343 + Sync() {
1.344 + readHolds = new ThreadLocalHoldCounter();
1.345 + setState(getState()); // ensures visibility of readHolds
1.346 + }
1.347 +
1.348 + /*
1.349 + * Acquires and releases use the same code for fair and
1.350 + * nonfair locks, but differ in whether/how they allow barging
1.351 + * when queues are non-empty.
1.352 + */
1.353 +
1.354 + /**
1.355 + * Returns true if the current thread, when trying to acquire
1.356 + * the read lock, and otherwise eligible to do so, should block
1.357 + * because of policy for overtaking other waiting threads.
1.358 + */
1.359 + abstract boolean readerShouldBlock();
1.360 +
1.361 + /**
1.362 + * Returns true if the current thread, when trying to acquire
1.363 + * the write lock, and otherwise eligible to do so, should block
1.364 + * because of policy for overtaking other waiting threads.
1.365 + */
1.366 + abstract boolean writerShouldBlock();
1.367 +
1.368 + /*
1.369 + * Note that tryRelease and tryAcquire can be called by
1.370 + * Conditions. So it is possible that their arguments contain
1.371 + * both read and write holds that are all released during a
1.372 + * condition wait and re-established in tryAcquire.
1.373 + */
1.374 +
1.375 + protected final boolean tryRelease(int releases) {
1.376 + if (!isHeldExclusively())
1.377 + throw new IllegalMonitorStateException();
1.378 + int nextc = getState() - releases;
1.379 + boolean free = exclusiveCount(nextc) == 0;
1.380 + if (free)
1.381 + setExclusiveOwnerThread(null);
1.382 + setState(nextc);
1.383 + return free;
1.384 + }
1.385 +
1.386 + protected final boolean tryAcquire(int acquires) {
1.387 + /*
1.388 + * Walkthrough:
1.389 + * 1. If read count nonzero or write count nonzero
1.390 + * and owner is a different thread, fail.
1.391 + * 2. If count would saturate, fail. (This can only
1.392 + * happen if count is already nonzero.)
1.393 + * 3. Otherwise, this thread is eligible for lock if
1.394 + * it is either a reentrant acquire or
1.395 + * queue policy allows it. If so, update state
1.396 + * and set owner.
1.397 + */
1.398 + Thread current = Thread.currentThread();
1.399 + int c = getState();
1.400 + int w = exclusiveCount(c);
1.401 + if (c != 0) {
1.402 + // (Note: if c != 0 and w == 0 then shared count != 0)
1.403 + if (w == 0 || current != getExclusiveOwnerThread())
1.404 + return false;
1.405 + if (w + exclusiveCount(acquires) > MAX_COUNT)
1.406 + throw new Error("Maximum lock count exceeded");
1.407 + // Reentrant acquire
1.408 + setState(c + acquires);
1.409 + return true;
1.410 + }
1.411 + if (writerShouldBlock() ||
1.412 + !compareAndSetState(c, c + acquires))
1.413 + return false;
1.414 + setExclusiveOwnerThread(current);
1.415 + return true;
1.416 + }
1.417 +
1.418 + protected final boolean tryReleaseShared(int unused) {
1.419 + Thread current = Thread.currentThread();
1.420 + if (firstReader == current) {
1.421 + // assert firstReaderHoldCount > 0;
1.422 + if (firstReaderHoldCount == 1)
1.423 + firstReader = null;
1.424 + else
1.425 + firstReaderHoldCount--;
1.426 + } else {
1.427 + HoldCounter rh = cachedHoldCounter;
1.428 + if (rh == null || rh.tid != current.getId())
1.429 + rh = readHolds.get();
1.430 + int count = rh.count;
1.431 + if (count <= 1) {
1.432 + readHolds.remove();
1.433 + if (count <= 0)
1.434 + throw unmatchedUnlockException();
1.435 + }
1.436 + --rh.count;
1.437 + }
1.438 + for (;;) {
1.439 + int c = getState();
1.440 + int nextc = c - SHARED_UNIT;
1.441 + if (compareAndSetState(c, nextc))
1.442 + // Releasing the read lock has no effect on readers,
1.443 + // but it may allow waiting writers to proceed if
1.444 + // both read and write locks are now free.
1.445 + return nextc == 0;
1.446 + }
1.447 + }
1.448 +
1.449 + private IllegalMonitorStateException unmatchedUnlockException() {
1.450 + return new IllegalMonitorStateException(
1.451 + "attempt to unlock read lock, not locked by current thread");
1.452 + }
1.453 +
1.454 + protected final int tryAcquireShared(int unused) {
1.455 + /*
1.456 + * Walkthrough:
1.457 + * 1. If write lock held by another thread, fail.
1.458 + * 2. Otherwise, this thread is eligible for
1.459 + * lock wrt state, so ask if it should block
1.460 + * because of queue policy. If not, try
1.461 + * to grant by CASing state and updating count.
1.462 + * Note that step does not check for reentrant
1.463 + * acquires, which is postponed to full version
1.464 + * to avoid having to check hold count in
1.465 + * the more typical non-reentrant case.
1.466 + * 3. If step 2 fails either because thread
1.467 + * apparently not eligible or CAS fails or count
1.468 + * saturated, chain to version with full retry loop.
1.469 + */
1.470 + Thread current = Thread.currentThread();
1.471 + int c = getState();
1.472 + if (exclusiveCount(c) != 0 &&
1.473 + getExclusiveOwnerThread() != current)
1.474 + return -1;
1.475 + int r = sharedCount(c);
1.476 + if (!readerShouldBlock() &&
1.477 + r < MAX_COUNT &&
1.478 + compareAndSetState(c, c + SHARED_UNIT)) {
1.479 + if (r == 0) {
1.480 + firstReader = current;
1.481 + firstReaderHoldCount = 1;
1.482 + } else if (firstReader == current) {
1.483 + firstReaderHoldCount++;
1.484 + } else {
1.485 + HoldCounter rh = cachedHoldCounter;
1.486 + if (rh == null || rh.tid != current.getId())
1.487 + cachedHoldCounter = rh = readHolds.get();
1.488 + else if (rh.count == 0)
1.489 + readHolds.set(rh);
1.490 + rh.count++;
1.491 + }
1.492 + return 1;
1.493 + }
1.494 + return fullTryAcquireShared(current);
1.495 + }
1.496 +
1.497 + /**
1.498 + * Full version of acquire for reads, that handles CAS misses
1.499 + * and reentrant reads not dealt with in tryAcquireShared.
1.500 + */
1.501 + final int fullTryAcquireShared(Thread current) {
1.502 + /*
1.503 + * This code is in part redundant with that in
1.504 + * tryAcquireShared but is simpler overall by not
1.505 + * complicating tryAcquireShared with interactions between
1.506 + * retries and lazily reading hold counts.
1.507 + */
1.508 + HoldCounter rh = null;
1.509 + for (;;) {
1.510 + int c = getState();
1.511 + if (exclusiveCount(c) != 0) {
1.512 + if (getExclusiveOwnerThread() != current)
1.513 + return -1;
1.514 + // else we hold the exclusive lock; blocking here
1.515 + // would cause deadlock.
1.516 + } else if (readerShouldBlock()) {
1.517 + // Make sure we're not acquiring read lock reentrantly
1.518 + if (firstReader == current) {
1.519 + // assert firstReaderHoldCount > 0;
1.520 + } else {
1.521 + if (rh == null) {
1.522 + rh = cachedHoldCounter;
1.523 + if (rh == null || rh.tid != current.getId()) {
1.524 + rh = readHolds.get();
1.525 + if (rh.count == 0)
1.526 + readHolds.remove();
1.527 + }
1.528 + }
1.529 + if (rh.count == 0)
1.530 + return -1;
1.531 + }
1.532 + }
1.533 + if (sharedCount(c) == MAX_COUNT)
1.534 + throw new Error("Maximum lock count exceeded");
1.535 + if (compareAndSetState(c, c + SHARED_UNIT)) {
1.536 + if (sharedCount(c) == 0) {
1.537 + firstReader = current;
1.538 + firstReaderHoldCount = 1;
1.539 + } else if (firstReader == current) {
1.540 + firstReaderHoldCount++;
1.541 + } else {
1.542 + if (rh == null)
1.543 + rh = cachedHoldCounter;
1.544 + if (rh == null || rh.tid != current.getId())
1.545 + rh = readHolds.get();
1.546 + else if (rh.count == 0)
1.547 + readHolds.set(rh);
1.548 + rh.count++;
1.549 + cachedHoldCounter = rh; // cache for release
1.550 + }
1.551 + return 1;
1.552 + }
1.553 + }
1.554 + }
1.555 +
1.556 + /**
1.557 + * Performs tryLock for write, enabling barging in both modes.
1.558 + * This is identical in effect to tryAcquire except for lack
1.559 + * of calls to writerShouldBlock.
1.560 + */
1.561 + final boolean tryWriteLock() {
1.562 + Thread current = Thread.currentThread();
1.563 + int c = getState();
1.564 + if (c != 0) {
1.565 + int w = exclusiveCount(c);
1.566 + if (w == 0 || current != getExclusiveOwnerThread())
1.567 + return false;
1.568 + if (w == MAX_COUNT)
1.569 + throw new Error("Maximum lock count exceeded");
1.570 + }
1.571 + if (!compareAndSetState(c, c + 1))
1.572 + return false;
1.573 + setExclusiveOwnerThread(current);
1.574 + return true;
1.575 + }
1.576 +
1.577 + /**
1.578 + * Performs tryLock for read, enabling barging in both modes.
1.579 + * This is identical in effect to tryAcquireShared except for
1.580 + * lack of calls to readerShouldBlock.
1.581 + */
1.582 + final boolean tryReadLock() {
1.583 + Thread current = Thread.currentThread();
1.584 + for (;;) {
1.585 + int c = getState();
1.586 + if (exclusiveCount(c) != 0 &&
1.587 + getExclusiveOwnerThread() != current)
1.588 + return false;
1.589 + int r = sharedCount(c);
1.590 + if (r == MAX_COUNT)
1.591 + throw new Error("Maximum lock count exceeded");
1.592 + if (compareAndSetState(c, c + SHARED_UNIT)) {
1.593 + if (r == 0) {
1.594 + firstReader = current;
1.595 + firstReaderHoldCount = 1;
1.596 + } else if (firstReader == current) {
1.597 + firstReaderHoldCount++;
1.598 + } else {
1.599 + HoldCounter rh = cachedHoldCounter;
1.600 + if (rh == null || rh.tid != current.getId())
1.601 + cachedHoldCounter = rh = readHolds.get();
1.602 + else if (rh.count == 0)
1.603 + readHolds.set(rh);
1.604 + rh.count++;
1.605 + }
1.606 + return true;
1.607 + }
1.608 + }
1.609 + }
1.610 +
1.611 + protected final boolean isHeldExclusively() {
1.612 + // While we must in general read state before owner,
1.613 + // we don't need to do so to check if current thread is owner
1.614 + return getExclusiveOwnerThread() == Thread.currentThread();
1.615 + }
1.616 +
1.617 + // Methods relayed to outer class
1.618 +
1.619 + final ConditionObject newCondition() {
1.620 + return new ConditionObject();
1.621 + }
1.622 +
1.623 + final Thread getOwner() {
1.624 + // Must read state before owner to ensure memory consistency
1.625 + return ((exclusiveCount(getState()) == 0) ?
1.626 + null :
1.627 + getExclusiveOwnerThread());
1.628 + }
1.629 +
1.630 + final int getReadLockCount() {
1.631 + return sharedCount(getState());
1.632 + }
1.633 +
1.634 + final boolean isWriteLocked() {
1.635 + return exclusiveCount(getState()) != 0;
1.636 + }
1.637 +
1.638 + final int getWriteHoldCount() {
1.639 + return isHeldExclusively() ? exclusiveCount(getState()) : 0;
1.640 + }
1.641 +
1.642 + final int getReadHoldCount() {
1.643 + if (getReadLockCount() == 0)
1.644 + return 0;
1.645 +
1.646 + Thread current = Thread.currentThread();
1.647 + if (firstReader == current)
1.648 + return firstReaderHoldCount;
1.649 +
1.650 + HoldCounter rh = cachedHoldCounter;
1.651 + if (rh != null && rh.tid == current.getId())
1.652 + return rh.count;
1.653 +
1.654 + int count = readHolds.get().count;
1.655 + if (count == 0) readHolds.remove();
1.656 + return count;
1.657 + }
1.658 +
1.659 + /**
1.660 + * Reconstitute this lock instance from a stream
1.661 + * @param s the stream
1.662 + */
1.663 + private void readObject(java.io.ObjectInputStream s)
1.664 + throws java.io.IOException, ClassNotFoundException {
1.665 + s.defaultReadObject();
1.666 + readHolds = new ThreadLocalHoldCounter();
1.667 + setState(0); // reset to unlocked state
1.668 + }
1.669 +
1.670 + final int getCount() { return getState(); }
1.671 + }
1.672 +
1.673 + /**
1.674 + * Nonfair version of Sync
1.675 + */
1.676 + static final class NonfairSync extends Sync {
1.677 + private static final long serialVersionUID = -8159625535654395037L;
1.678 + final boolean writerShouldBlock() {
1.679 + return false; // writers can always barge
1.680 + }
1.681 + final boolean readerShouldBlock() {
1.682 + /* As a heuristic to avoid indefinite writer starvation,
1.683 + * block if the thread that momentarily appears to be head
1.684 + * of queue, if one exists, is a waiting writer. This is
1.685 + * only a probabilistic effect since a new reader will not
1.686 + * block if there is a waiting writer behind other enabled
1.687 + * readers that have not yet drained from the queue.
1.688 + */
1.689 + return apparentlyFirstQueuedIsExclusive();
1.690 + }
1.691 + }
1.692 +
1.693 + /**
1.694 + * Fair version of Sync
1.695 + */
1.696 + static final class FairSync extends Sync {
1.697 + private static final long serialVersionUID = -2274990926593161451L;
1.698 + final boolean writerShouldBlock() {
1.699 + return hasQueuedPredecessors();
1.700 + }
1.701 + final boolean readerShouldBlock() {
1.702 + return hasQueuedPredecessors();
1.703 + }
1.704 + }
1.705 +
1.706 + /**
1.707 + * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
1.708 + */
1.709 + public static class ReadLock implements Lock, java.io.Serializable {
1.710 + private static final long serialVersionUID = -5992448646407690164L;
1.711 + private final Sync sync;
1.712 +
1.713 + /**
1.714 + * Constructor for use by subclasses
1.715 + *
1.716 + * @param lock the outer lock object
1.717 + * @throws NullPointerException if the lock is null
1.718 + */
1.719 + protected ReadLock(ReentrantReadWriteLock lock) {
1.720 + sync = lock.sync;
1.721 + }
1.722 +
1.723 + /**
1.724 + * Acquires the read lock.
1.725 + *
1.726 + * <p>Acquires the read lock if the write lock is not held by
1.727 + * another thread and returns immediately.
1.728 + *
1.729 + * <p>If the write lock is held by another thread then
1.730 + * the current thread becomes disabled for thread scheduling
1.731 + * purposes and lies dormant until the read lock has been acquired.
1.732 + */
1.733 + public void lock() {
1.734 + sync.acquireShared(1);
1.735 + }
1.736 +
1.737 + /**
1.738 + * Acquires the read lock unless the current thread is
1.739 + * {@linkplain Thread#interrupt interrupted}.
1.740 + *
1.741 + * <p>Acquires the read lock if the write lock is not held
1.742 + * by another thread and returns immediately.
1.743 + *
1.744 + * <p>If the write lock is held by another thread then the
1.745 + * current thread becomes disabled for thread scheduling
1.746 + * purposes and lies dormant until one of two things happens:
1.747 + *
1.748 + * <ul>
1.749 + *
1.750 + * <li>The read lock is acquired by the current thread; or
1.751 + *
1.752 + * <li>Some other thread {@linkplain Thread#interrupt interrupts}
1.753 + * the current thread.
1.754 + *
1.755 + * </ul>
1.756 + *
1.757 + * <p>If the current thread:
1.758 + *
1.759 + * <ul>
1.760 + *
1.761 + * <li>has its interrupted status set on entry to this method; or
1.762 + *
1.763 + * <li>is {@linkplain Thread#interrupt interrupted} while
1.764 + * acquiring the read lock,
1.765 + *
1.766 + * </ul>
1.767 + *
1.768 + * then {@link InterruptedException} is thrown and the current
1.769 + * thread's interrupted status is cleared.
1.770 + *
1.771 + * <p>In this implementation, as this method is an explicit
1.772 + * interruption point, preference is given to responding to
1.773 + * the interrupt over normal or reentrant acquisition of the
1.774 + * lock.
1.775 + *
1.776 + * @throws InterruptedException if the current thread is interrupted
1.777 + */
1.778 + public void lockInterruptibly() throws InterruptedException {
1.779 + sync.acquireSharedInterruptibly(1);
1.780 + }
1.781 +
1.782 + /**
1.783 + * Acquires the read lock only if the write lock is not held by
1.784 + * another thread at the time of invocation.
1.785 + *
1.786 + * <p>Acquires the read lock if the write lock is not held by
1.787 + * another thread and returns immediately with the value
1.788 + * {@code true}. Even when this lock has been set to use a
1.789 + * fair ordering policy, a call to {@code tryLock()}
1.790 + * <em>will</em> immediately acquire the read lock if it is
1.791 + * available, whether or not other threads are currently
1.792 + * waiting for the read lock. This "barging" behavior
1.793 + * can be useful in certain circumstances, even though it
1.794 + * breaks fairness. If you want to honor the fairness setting
1.795 + * for this lock, then use {@link #tryLock(long, TimeUnit)
1.796 + * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
1.797 + * (it also detects interruption).
1.798 + *
1.799 + * <p>If the write lock is held by another thread then
1.800 + * this method will return immediately with the value
1.801 + * {@code false}.
1.802 + *
1.803 + * @return {@code true} if the read lock was acquired
1.804 + */
1.805 + public boolean tryLock() {
1.806 + return sync.tryReadLock();
1.807 + }
1.808 +
1.809 + /**
1.810 + * Acquires the read lock if the write lock is not held by
1.811 + * another thread within the given waiting time and the
1.812 + * current thread has not been {@linkplain Thread#interrupt
1.813 + * interrupted}.
1.814 + *
1.815 + * <p>Acquires the read lock if the write lock is not held by
1.816 + * another thread and returns immediately with the value
1.817 + * {@code true}. If this lock has been set to use a fair
1.818 + * ordering policy then an available lock <em>will not</em> be
1.819 + * acquired if any other threads are waiting for the
1.820 + * lock. This is in contrast to the {@link #tryLock()}
1.821 + * method. If you want a timed {@code tryLock} that does
1.822 + * permit barging on a fair lock then combine the timed and
1.823 + * un-timed forms together:
1.824 + *
1.825 + * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
1.826 + * </pre>
1.827 + *
1.828 + * <p>If the write lock is held by another thread then the
1.829 + * current thread becomes disabled for thread scheduling
1.830 + * purposes and lies dormant until one of three things happens:
1.831 + *
1.832 + * <ul>
1.833 + *
1.834 + * <li>The read lock is acquired by the current thread; or
1.835 + *
1.836 + * <li>Some other thread {@linkplain Thread#interrupt interrupts}
1.837 + * the current thread; or
1.838 + *
1.839 + * <li>The specified waiting time elapses.
1.840 + *
1.841 + * </ul>
1.842 + *
1.843 + * <p>If the read lock is acquired then the value {@code true} is
1.844 + * returned.
1.845 + *
1.846 + * <p>If the current thread:
1.847 + *
1.848 + * <ul>
1.849 + *
1.850 + * <li>has its interrupted status set on entry to this method; or
1.851 + *
1.852 + * <li>is {@linkplain Thread#interrupt interrupted} while
1.853 + * acquiring the read lock,
1.854 + *
1.855 + * </ul> then {@link InterruptedException} is thrown and the
1.856 + * current thread's interrupted status is cleared.
1.857 + *
1.858 + * <p>If the specified waiting time elapses then the value
1.859 + * {@code false} is returned. If the time is less than or
1.860 + * equal to zero, the method will not wait at all.
1.861 + *
1.862 + * <p>In this implementation, as this method is an explicit
1.863 + * interruption point, preference is given to responding to
1.864 + * the interrupt over normal or reentrant acquisition of the
1.865 + * lock, and over reporting the elapse of the waiting time.
1.866 + *
1.867 + * @param timeout the time to wait for the read lock
1.868 + * @param unit the time unit of the timeout argument
1.869 + * @return {@code true} if the read lock was acquired
1.870 + * @throws InterruptedException if the current thread is interrupted
1.871 + * @throws NullPointerException if the time unit is null
1.872 + *
1.873 + */
1.874 + public boolean tryLock(long timeout, TimeUnit unit)
1.875 + throws InterruptedException {
1.876 + return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
1.877 + }
1.878 +
1.879 + /**
1.880 + * Attempts to release this lock.
1.881 + *
1.882 + * <p> If the number of readers is now zero then the lock
1.883 + * is made available for write lock attempts.
1.884 + */
1.885 + public void unlock() {
1.886 + sync.releaseShared(1);
1.887 + }
1.888 +
1.889 + /**
1.890 + * Throws {@code UnsupportedOperationException} because
1.891 + * {@code ReadLocks} do not support conditions.
1.892 + *
1.893 + * @throws UnsupportedOperationException always
1.894 + */
1.895 + public Condition newCondition() {
1.896 + throw new UnsupportedOperationException();
1.897 + }
1.898 +
1.899 + /**
1.900 + * Returns a string identifying this lock, as well as its lock state.
1.901 + * The state, in brackets, includes the String {@code "Read locks ="}
1.902 + * followed by the number of held read locks.
1.903 + *
1.904 + * @return a string identifying this lock, as well as its lock state
1.905 + */
1.906 + public String toString() {
1.907 + int r = sync.getReadLockCount();
1.908 + return super.toString() +
1.909 + "[Read locks = " + r + "]";
1.910 + }
1.911 + }
1.912 +
1.913 + /**
1.914 + * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
1.915 + */
1.916 + public static class WriteLock implements Lock, java.io.Serializable {
1.917 + private static final long serialVersionUID = -4992448646407690164L;
1.918 + private final Sync sync;
1.919 +
1.920 + /**
1.921 + * Constructor for use by subclasses
1.922 + *
1.923 + * @param lock the outer lock object
1.924 + * @throws NullPointerException if the lock is null
1.925 + */
1.926 + protected WriteLock(ReentrantReadWriteLock lock) {
1.927 + sync = lock.sync;
1.928 + }
1.929 +
1.930 + /**
1.931 + * Acquires the write lock.
1.932 + *
1.933 + * <p>Acquires the write lock if neither the read nor write lock
1.934 + * are held by another thread
1.935 + * and returns immediately, setting the write lock hold count to
1.936 + * one.
1.937 + *
1.938 + * <p>If the current thread already holds the write lock then the
1.939 + * hold count is incremented by one and the method returns
1.940 + * immediately.
1.941 + *
1.942 + * <p>If the lock is held by another thread then the current
1.943 + * thread becomes disabled for thread scheduling purposes and
1.944 + * lies dormant until the write lock has been acquired, at which
1.945 + * time the write lock hold count is set to one.
1.946 + */
1.947 + public void lock() {
1.948 + sync.acquire(1);
1.949 + }
1.950 +
1.951 + /**
1.952 + * Acquires the write lock unless the current thread is
1.953 + * {@linkplain Thread#interrupt interrupted}.
1.954 + *
1.955 + * <p>Acquires the write lock if neither the read nor write lock
1.956 + * are held by another thread
1.957 + * and returns immediately, setting the write lock hold count to
1.958 + * one.
1.959 + *
1.960 + * <p>If the current thread already holds this lock then the
1.961 + * hold count is incremented by one and the method returns
1.962 + * immediately.
1.963 + *
1.964 + * <p>If the lock is held by another thread then the current
1.965 + * thread becomes disabled for thread scheduling purposes and
1.966 + * lies dormant until one of two things happens:
1.967 + *
1.968 + * <ul>
1.969 + *
1.970 + * <li>The write lock is acquired by the current thread; or
1.971 + *
1.972 + * <li>Some other thread {@linkplain Thread#interrupt interrupts}
1.973 + * the current thread.
1.974 + *
1.975 + * </ul>
1.976 + *
1.977 + * <p>If the write lock is acquired by the current thread then the
1.978 + * lock hold count is set to one.
1.979 + *
1.980 + * <p>If the current thread:
1.981 + *
1.982 + * <ul>
1.983 + *
1.984 + * <li>has its interrupted status set on entry to this method;
1.985 + * or
1.986 + *
1.987 + * <li>is {@linkplain Thread#interrupt interrupted} while
1.988 + * acquiring the write lock,
1.989 + *
1.990 + * </ul>
1.991 + *
1.992 + * then {@link InterruptedException} is thrown and the current
1.993 + * thread's interrupted status is cleared.
1.994 + *
1.995 + * <p>In this implementation, as this method is an explicit
1.996 + * interruption point, preference is given to responding to
1.997 + * the interrupt over normal or reentrant acquisition of the
1.998 + * lock.
1.999 + *
1.1000 + * @throws InterruptedException if the current thread is interrupted
1.1001 + */
1.1002 + public void lockInterruptibly() throws InterruptedException {
1.1003 + sync.acquireInterruptibly(1);
1.1004 + }
1.1005 +
1.1006 + /**
1.1007 + * Acquires the write lock only if it is not held by another thread
1.1008 + * at the time of invocation.
1.1009 + *
1.1010 + * <p>Acquires the write lock if neither the read nor write lock
1.1011 + * are held by another thread
1.1012 + * and returns immediately with the value {@code true},
1.1013 + * setting the write lock hold count to one. Even when this lock has
1.1014 + * been set to use a fair ordering policy, a call to
1.1015 + * {@code tryLock()} <em>will</em> immediately acquire the
1.1016 + * lock if it is available, whether or not other threads are
1.1017 + * currently waiting for the write lock. This "barging"
1.1018 + * behavior can be useful in certain circumstances, even
1.1019 + * though it breaks fairness. If you want to honor the
1.1020 + * fairness setting for this lock, then use {@link
1.1021 + * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
1.1022 + * which is almost equivalent (it also detects interruption).
1.1023 + *
1.1024 + * <p> If the current thread already holds this lock then the
1.1025 + * hold count is incremented by one and the method returns
1.1026 + * {@code true}.
1.1027 + *
1.1028 + * <p>If the lock is held by another thread then this method
1.1029 + * will return immediately with the value {@code false}.
1.1030 + *
1.1031 + * @return {@code true} if the lock was free and was acquired
1.1032 + * by the current thread, or the write lock was already held
1.1033 + * by the current thread; and {@code false} otherwise.
1.1034 + */
1.1035 + public boolean tryLock( ) {
1.1036 + return sync.tryWriteLock();
1.1037 + }
1.1038 +
1.1039 + /**
1.1040 + * Acquires the write lock if it is not held by another thread
1.1041 + * within the given waiting time and the current thread has
1.1042 + * not been {@linkplain Thread#interrupt interrupted}.
1.1043 + *
1.1044 + * <p>Acquires the write lock if neither the read nor write lock
1.1045 + * are held by another thread
1.1046 + * and returns immediately with the value {@code true},
1.1047 + * setting the write lock hold count to one. If this lock has been
1.1048 + * set to use a fair ordering policy then an available lock
1.1049 + * <em>will not</em> be acquired if any other threads are
1.1050 + * waiting for the write lock. This is in contrast to the {@link
1.1051 + * #tryLock()} method. If you want a timed {@code tryLock}
1.1052 + * that does permit barging on a fair lock then combine the
1.1053 + * timed and un-timed forms together:
1.1054 + *
1.1055 + * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
1.1056 + * </pre>
1.1057 + *
1.1058 + * <p>If the current thread already holds this lock then the
1.1059 + * hold count is incremented by one and the method returns
1.1060 + * {@code true}.
1.1061 + *
1.1062 + * <p>If the lock is held by another thread then the current
1.1063 + * thread becomes disabled for thread scheduling purposes and
1.1064 + * lies dormant until one of three things happens:
1.1065 + *
1.1066 + * <ul>
1.1067 + *
1.1068 + * <li>The write lock is acquired by the current thread; or
1.1069 + *
1.1070 + * <li>Some other thread {@linkplain Thread#interrupt interrupts}
1.1071 + * the current thread; or
1.1072 + *
1.1073 + * <li>The specified waiting time elapses
1.1074 + *
1.1075 + * </ul>
1.1076 + *
1.1077 + * <p>If the write lock is acquired then the value {@code true} is
1.1078 + * returned and the write lock hold count is set to one.
1.1079 + *
1.1080 + * <p>If the current thread:
1.1081 + *
1.1082 + * <ul>
1.1083 + *
1.1084 + * <li>has its interrupted status set on entry to this method;
1.1085 + * or
1.1086 + *
1.1087 + * <li>is {@linkplain Thread#interrupt interrupted} while
1.1088 + * acquiring the write lock,
1.1089 + *
1.1090 + * </ul>
1.1091 + *
1.1092 + * then {@link InterruptedException} is thrown and the current
1.1093 + * thread's interrupted status is cleared.
1.1094 + *
1.1095 + * <p>If the specified waiting time elapses then the value
1.1096 + * {@code false} is returned. If the time is less than or
1.1097 + * equal to zero, the method will not wait at all.
1.1098 + *
1.1099 + * <p>In this implementation, as this method is an explicit
1.1100 + * interruption point, preference is given to responding to
1.1101 + * the interrupt over normal or reentrant acquisition of the
1.1102 + * lock, and over reporting the elapse of the waiting time.
1.1103 + *
1.1104 + * @param timeout the time to wait for the write lock
1.1105 + * @param unit the time unit of the timeout argument
1.1106 + *
1.1107 + * @return {@code true} if the lock was free and was acquired
1.1108 + * by the current thread, or the write lock was already held by the
1.1109 + * current thread; and {@code false} if the waiting time
1.1110 + * elapsed before the lock could be acquired.
1.1111 + *
1.1112 + * @throws InterruptedException if the current thread is interrupted
1.1113 + * @throws NullPointerException if the time unit is null
1.1114 + *
1.1115 + */
1.1116 + public boolean tryLock(long timeout, TimeUnit unit)
1.1117 + throws InterruptedException {
1.1118 + return sync.tryAcquireNanos(1, unit.toNanos(timeout));
1.1119 + }
1.1120 +
1.1121 + /**
1.1122 + * Attempts to release this lock.
1.1123 + *
1.1124 + * <p>If the current thread is the holder of this lock then
1.1125 + * the hold count is decremented. If the hold count is now
1.1126 + * zero then the lock is released. If the current thread is
1.1127 + * not the holder of this lock then {@link
1.1128 + * IllegalMonitorStateException} is thrown.
1.1129 + *
1.1130 + * @throws IllegalMonitorStateException if the current thread does not
1.1131 + * hold this lock.
1.1132 + */
1.1133 + public void unlock() {
1.1134 + sync.release(1);
1.1135 + }
1.1136 +
1.1137 + /**
1.1138 + * Returns a {@link Condition} instance for use with this
1.1139 + * {@link Lock} instance.
1.1140 + * <p>The returned {@link Condition} instance supports the same
1.1141 + * usages as do the {@link Object} monitor methods ({@link
1.1142 + * Object#wait() wait}, {@link Object#notify notify}, and {@link
1.1143 + * Object#notifyAll notifyAll}) when used with the built-in
1.1144 + * monitor lock.
1.1145 + *
1.1146 + * <ul>
1.1147 + *
1.1148 + * <li>If this write lock is not held when any {@link
1.1149 + * Condition} method is called then an {@link
1.1150 + * IllegalMonitorStateException} is thrown. (Read locks are
1.1151 + * held independently of write locks, so are not checked or
1.1152 + * affected. However it is essentially always an error to
1.1153 + * invoke a condition waiting method when the current thread
1.1154 + * has also acquired read locks, since other threads that
1.1155 + * could unblock it will not be able to acquire the write
1.1156 + * lock.)
1.1157 + *
1.1158 + * <li>When the condition {@linkplain Condition#await() waiting}
1.1159 + * methods are called the write lock is released and, before
1.1160 + * they return, the write lock is reacquired and the lock hold
1.1161 + * count restored to what it was when the method was called.
1.1162 + *
1.1163 + * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
1.1164 + * waiting then the wait will terminate, an {@link
1.1165 + * InterruptedException} will be thrown, and the thread's
1.1166 + * interrupted status will be cleared.
1.1167 + *
1.1168 + * <li> Waiting threads are signalled in FIFO order.
1.1169 + *
1.1170 + * <li>The ordering of lock reacquisition for threads returning
1.1171 + * from waiting methods is the same as for threads initially
1.1172 + * acquiring the lock, which is in the default case not specified,
1.1173 + * but for <em>fair</em> locks favors those threads that have been
1.1174 + * waiting the longest.
1.1175 + *
1.1176 + * </ul>
1.1177 + *
1.1178 + * @return the Condition object
1.1179 + */
1.1180 + public Condition newCondition() {
1.1181 + return sync.newCondition();
1.1182 + }
1.1183 +
1.1184 + /**
1.1185 + * Returns a string identifying this lock, as well as its lock
1.1186 + * state. The state, in brackets includes either the String
1.1187 + * {@code "Unlocked"} or the String {@code "Locked by"}
1.1188 + * followed by the {@linkplain Thread#getName name} of the owning thread.
1.1189 + *
1.1190 + * @return a string identifying this lock, as well as its lock state
1.1191 + */
1.1192 + public String toString() {
1.1193 + Thread o = sync.getOwner();
1.1194 + return super.toString() + ((o == null) ?
1.1195 + "[Unlocked]" :
1.1196 + "[Locked by thread " + o.getName() + "]");
1.1197 + }
1.1198 +
1.1199 + /**
1.1200 + * Queries if this write lock is held by the current thread.
1.1201 + * Identical in effect to {@link
1.1202 + * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
1.1203 + *
1.1204 + * @return {@code true} if the current thread holds this lock and
1.1205 + * {@code false} otherwise
1.1206 + * @since 1.6
1.1207 + */
1.1208 + public boolean isHeldByCurrentThread() {
1.1209 + return sync.isHeldExclusively();
1.1210 + }
1.1211 +
1.1212 + /**
1.1213 + * Queries the number of holds on this write lock by the current
1.1214 + * thread. A thread has a hold on a lock for each lock action
1.1215 + * that is not matched by an unlock action. Identical in effect
1.1216 + * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
1.1217 + *
1.1218 + * @return the number of holds on this lock by the current thread,
1.1219 + * or zero if this lock is not held by the current thread
1.1220 + * @since 1.6
1.1221 + */
1.1222 + public int getHoldCount() {
1.1223 + return sync.getWriteHoldCount();
1.1224 + }
1.1225 + }
1.1226 +
1.1227 + // Instrumentation and status
1.1228 +
1.1229 + /**
1.1230 + * Returns {@code true} if this lock has fairness set true.
1.1231 + *
1.1232 + * @return {@code true} if this lock has fairness set true
1.1233 + */
1.1234 + public final boolean isFair() {
1.1235 + return sync instanceof FairSync;
1.1236 + }
1.1237 +
1.1238 + /**
1.1239 + * Returns the thread that currently owns the write lock, or
1.1240 + * {@code null} if not owned. When this method is called by a
1.1241 + * thread that is not the owner, the return value reflects a
1.1242 + * best-effort approximation of current lock status. For example,
1.1243 + * the owner may be momentarily {@code null} even if there are
1.1244 + * threads trying to acquire the lock but have not yet done so.
1.1245 + * This method is designed to facilitate construction of
1.1246 + * subclasses that provide more extensive lock monitoring
1.1247 + * facilities.
1.1248 + *
1.1249 + * @return the owner, or {@code null} if not owned
1.1250 + */
1.1251 + protected Thread getOwner() {
1.1252 + return sync.getOwner();
1.1253 + }
1.1254 +
1.1255 + /**
1.1256 + * Queries the number of read locks held for this lock. This
1.1257 + * method is designed for use in monitoring system state, not for
1.1258 + * synchronization control.
1.1259 + * @return the number of read locks held.
1.1260 + */
1.1261 + public int getReadLockCount() {
1.1262 + return sync.getReadLockCount();
1.1263 + }
1.1264 +
1.1265 + /**
1.1266 + * Queries if the write lock is held by any thread. This method is
1.1267 + * designed for use in monitoring system state, not for
1.1268 + * synchronization control.
1.1269 + *
1.1270 + * @return {@code true} if any thread holds the write lock and
1.1271 + * {@code false} otherwise
1.1272 + */
1.1273 + public boolean isWriteLocked() {
1.1274 + return sync.isWriteLocked();
1.1275 + }
1.1276 +
1.1277 + /**
1.1278 + * Queries if the write lock is held by the current thread.
1.1279 + *
1.1280 + * @return {@code true} if the current thread holds the write lock and
1.1281 + * {@code false} otherwise
1.1282 + */
1.1283 + public boolean isWriteLockedByCurrentThread() {
1.1284 + return sync.isHeldExclusively();
1.1285 + }
1.1286 +
1.1287 + /**
1.1288 + * Queries the number of reentrant write holds on this lock by the
1.1289 + * current thread. A writer thread has a hold on a lock for
1.1290 + * each lock action that is not matched by an unlock action.
1.1291 + *
1.1292 + * @return the number of holds on the write lock by the current thread,
1.1293 + * or zero if the write lock is not held by the current thread
1.1294 + */
1.1295 + public int getWriteHoldCount() {
1.1296 + return sync.getWriteHoldCount();
1.1297 + }
1.1298 +
1.1299 + /**
1.1300 + * Queries the number of reentrant read holds on this lock by the
1.1301 + * current thread. A reader thread has a hold on a lock for
1.1302 + * each lock action that is not matched by an unlock action.
1.1303 + *
1.1304 + * @return the number of holds on the read lock by the current thread,
1.1305 + * or zero if the read lock is not held by the current thread
1.1306 + * @since 1.6
1.1307 + */
1.1308 + public int getReadHoldCount() {
1.1309 + return sync.getReadHoldCount();
1.1310 + }
1.1311 +
1.1312 + /**
1.1313 + * Returns a collection containing threads that may be waiting to
1.1314 + * acquire the write lock. Because the actual set of threads may
1.1315 + * change dynamically while constructing this result, the returned
1.1316 + * collection is only a best-effort estimate. The elements of the
1.1317 + * returned collection are in no particular order. This method is
1.1318 + * designed to facilitate construction of subclasses that provide
1.1319 + * more extensive lock monitoring facilities.
1.1320 + *
1.1321 + * @return the collection of threads
1.1322 + */
1.1323 + protected Collection<Thread> getQueuedWriterThreads() {
1.1324 + return sync.getExclusiveQueuedThreads();
1.1325 + }
1.1326 +
1.1327 + /**
1.1328 + * Returns a collection containing threads that may be waiting to
1.1329 + * acquire the read lock. Because the actual set of threads may
1.1330 + * change dynamically while constructing this result, the returned
1.1331 + * collection is only a best-effort estimate. The elements of the
1.1332 + * returned collection are in no particular order. This method is
1.1333 + * designed to facilitate construction of subclasses that provide
1.1334 + * more extensive lock monitoring facilities.
1.1335 + *
1.1336 + * @return the collection of threads
1.1337 + */
1.1338 + protected Collection<Thread> getQueuedReaderThreads() {
1.1339 + return sync.getSharedQueuedThreads();
1.1340 + }
1.1341 +
1.1342 + /**
1.1343 + * Queries whether any threads are waiting to acquire the read or
1.1344 + * write lock. Note that because cancellations may occur at any
1.1345 + * time, a {@code true} return does not guarantee that any other
1.1346 + * thread will ever acquire a lock. This method is designed
1.1347 + * primarily for use in monitoring of the system state.
1.1348 + *
1.1349 + * @return {@code true} if there may be other threads waiting to
1.1350 + * acquire the lock
1.1351 + */
1.1352 + public final boolean hasQueuedThreads() {
1.1353 + return sync.hasQueuedThreads();
1.1354 + }
1.1355 +
1.1356 + /**
1.1357 + * Queries whether the given thread is waiting to acquire either
1.1358 + * the read or write lock. Note that because cancellations may
1.1359 + * occur at any time, a {@code true} return does not guarantee
1.1360 + * that this thread will ever acquire a lock. This method is
1.1361 + * designed primarily for use in monitoring of the system state.
1.1362 + *
1.1363 + * @param thread the thread
1.1364 + * @return {@code true} if the given thread is queued waiting for this lock
1.1365 + * @throws NullPointerException if the thread is null
1.1366 + */
1.1367 + public final boolean hasQueuedThread(Thread thread) {
1.1368 + return sync.isQueued(thread);
1.1369 + }
1.1370 +
1.1371 + /**
1.1372 + * Returns an estimate of the number of threads waiting to acquire
1.1373 + * either the read or write lock. The value is only an estimate
1.1374 + * because the number of threads may change dynamically while this
1.1375 + * method traverses internal data structures. This method is
1.1376 + * designed for use in monitoring of the system state, not for
1.1377 + * synchronization control.
1.1378 + *
1.1379 + * @return the estimated number of threads waiting for this lock
1.1380 + */
1.1381 + public final int getQueueLength() {
1.1382 + return sync.getQueueLength();
1.1383 + }
1.1384 +
1.1385 + /**
1.1386 + * Returns a collection containing threads that may be waiting to
1.1387 + * acquire either the read or write lock. Because the actual set
1.1388 + * of threads may change dynamically while constructing this
1.1389 + * result, the returned collection is only a best-effort estimate.
1.1390 + * The elements of the returned collection are in no particular
1.1391 + * order. This method is designed to facilitate construction of
1.1392 + * subclasses that provide more extensive monitoring facilities.
1.1393 + *
1.1394 + * @return the collection of threads
1.1395 + */
1.1396 + protected Collection<Thread> getQueuedThreads() {
1.1397 + return sync.getQueuedThreads();
1.1398 + }
1.1399 +
1.1400 + /**
1.1401 + * Queries whether any threads are waiting on the given condition
1.1402 + * associated with the write lock. Note that because timeouts and
1.1403 + * interrupts may occur at any time, a {@code true} return does
1.1404 + * not guarantee that a future {@code signal} will awaken any
1.1405 + * threads. This method is designed primarily for use in
1.1406 + * monitoring of the system state.
1.1407 + *
1.1408 + * @param condition the condition
1.1409 + * @return {@code true} if there are any waiting threads
1.1410 + * @throws IllegalMonitorStateException if this lock is not held
1.1411 + * @throws IllegalArgumentException if the given condition is
1.1412 + * not associated with this lock
1.1413 + * @throws NullPointerException if the condition is null
1.1414 + */
1.1415 + public boolean hasWaiters(Condition condition) {
1.1416 + if (condition == null)
1.1417 + throw new NullPointerException();
1.1418 + if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1.1419 + throw new IllegalArgumentException("not owner");
1.1420 + return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
1.1421 + }
1.1422 +
1.1423 + /**
1.1424 + * Returns an estimate of the number of threads waiting on the
1.1425 + * given condition associated with the write lock. Note that because
1.1426 + * timeouts and interrupts may occur at any time, the estimate
1.1427 + * serves only as an upper bound on the actual number of waiters.
1.1428 + * This method is designed for use in monitoring of the system
1.1429 + * state, not for synchronization control.
1.1430 + *
1.1431 + * @param condition the condition
1.1432 + * @return the estimated number of waiting threads
1.1433 + * @throws IllegalMonitorStateException if this lock is not held
1.1434 + * @throws IllegalArgumentException if the given condition is
1.1435 + * not associated with this lock
1.1436 + * @throws NullPointerException if the condition is null
1.1437 + */
1.1438 + public int getWaitQueueLength(Condition condition) {
1.1439 + if (condition == null)
1.1440 + throw new NullPointerException();
1.1441 + if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1.1442 + throw new IllegalArgumentException("not owner");
1.1443 + return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
1.1444 + }
1.1445 +
1.1446 + /**
1.1447 + * Returns a collection containing those threads that may be
1.1448 + * waiting on the given condition associated with the write lock.
1.1449 + * Because the actual set of threads may change dynamically while
1.1450 + * constructing this result, the returned collection is only a
1.1451 + * best-effort estimate. The elements of the returned collection
1.1452 + * are in no particular order. This method is designed to
1.1453 + * facilitate construction of subclasses that provide more
1.1454 + * extensive condition monitoring facilities.
1.1455 + *
1.1456 + * @param condition the condition
1.1457 + * @return the collection of threads
1.1458 + * @throws IllegalMonitorStateException if this lock is not held
1.1459 + * @throws IllegalArgumentException if the given condition is
1.1460 + * not associated with this lock
1.1461 + * @throws NullPointerException if the condition is null
1.1462 + */
1.1463 + protected Collection<Thread> getWaitingThreads(Condition condition) {
1.1464 + if (condition == null)
1.1465 + throw new NullPointerException();
1.1466 + if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1.1467 + throw new IllegalArgumentException("not owner");
1.1468 + return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
1.1469 + }
1.1470 +
1.1471 + /**
1.1472 + * Returns a string identifying this lock, as well as its lock state.
1.1473 + * The state, in brackets, includes the String {@code "Write locks ="}
1.1474 + * followed by the number of reentrantly held write locks, and the
1.1475 + * String {@code "Read locks ="} followed by the number of held
1.1476 + * read locks.
1.1477 + *
1.1478 + * @return a string identifying this lock, as well as its lock state
1.1479 + */
1.1480 + public String toString() {
1.1481 + int c = sync.getCount();
1.1482 + int w = Sync.exclusiveCount(c);
1.1483 + int r = Sync.sharedCount(c);
1.1484 +
1.1485 + return super.toString() +
1.1486 + "[Write locks = " + w + ", Read locks = " + r + "]";
1.1487 + }
1.1488 +
1.1489 +}