Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

来源:互联网 发布:橙光制作工具mac 编辑:程序博客网 时间:2024/06/07 07:18

Java多线程系列-目录
[笔记][Java7并发编程实战手册]系列目录


概要

Java的JUC(java.util.concurrent)包中的锁包括”独占锁”和”共享锁”。
在“Java多线程系列–“JUC锁”02之 互斥锁ReentrantLock ”中,对Java的独占锁进行了说明。
本章对Java的“共享锁”进行介绍,JUC中的共享锁有CountDownLatch, CyclicBarrier, Semaphore, ReentrantReadWriteLock等;
ReentrantReadWriteLock为蓝本对共享锁进行说明。


ReadWriteLock 和 ReentrantReadWriteLock介绍

ReadWriteLock,顾名思义,是读写锁。它维护了一对相关的锁 — — “读取锁”和“写入锁”,一个用于读取操作,另一个用于写入操作。
“读取锁”用于只读操作,它是“共享锁”,能同时被多个线程获取。
“写入锁”用于写入操作,它是“独占锁”,写入锁只能被一个线程锁获取。

注意:不能同时存在读取锁和写入锁!(在读取锁操作里面不能写入数据!)
ReadWriteLock是一个接口。ReentrantReadWriteLock是它的实现类,ReentrantReadWriteLock包括子类ReadLock和WriteLock。


ReadWriteLock 和 ReentrantReadWriteLock函数列表

ReadWriteLock函数列表

// 返回用于读取操作的锁。Lock readLock()// 返回用于写入操作的锁。Lock writeLock()

ReentrantReadWriteLock函数列表

// 创建一个新的 ReentrantReadWriteLock,默认是采用“非公平策略”。ReentrantReadWriteLock()// 创建一个新的 ReentrantReadWriteLock,fair是“公平策略”。fair为true,意味着公平策略;否则,意味着非公平策略。ReentrantReadWriteLock(boolean fair)// 返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null。protected Thread getOwner()// 返回一个 collection,它包含可能正在等待获取读取锁的线程。protected Collection<Thread> getQueuedReaderThreads()// 返回一个 collection,它包含可能正在等待获取读取或写入锁的线程。protected Collection<Thread> getQueuedThreads()// 返回一个 collection,它包含可能正在等待获取写入锁的线程。protected Collection<Thread> getQueuedWriterThreads()// 返回等待获取读取或写入锁的线程估计数目。int getQueueLength()// 查询当前线程在此锁上保持的重入读取锁数量。int getReadHoldCount()// 查询为此锁保持的读取锁数量。int getReadLockCount()// 返回一个 collection,它包含可能正在等待与写入锁相关的给定条件的那些线程。protected Collection<Thread> getWaitingThreads(Condition condition)// 返回正等待与写入锁相关的给定条件的线程估计数目。int getWaitQueueLength(Condition condition)// 查询当前线程在此锁上保持的重入写入锁数量。int getWriteHoldCount()// 查询是否给定线程正在等待获取读取或写入锁。boolean hasQueuedThread(Thread thread)// 查询是否所有的线程正在等待获取读取或写入锁。boolean hasQueuedThreads()// 查询是否有些线程正在等待与写入锁有关的给定条件。boolean hasWaiters(Condition condition)// 如果此锁将公平性设置为 ture,则返回 trueboolean isFair()// 查询是否某个线程保持了写入锁。boolean isWriteLocked()// 查询当前线程是否保持了写入锁。boolean isWriteLockedByCurrentThread()// 返回用于读取操作的锁。ReentrantReadWriteLock.ReadLock readLock()// 返回用于写入操作的锁。ReentrantReadWriteLock.WriteLock writeLock()

ReentrantReadWriteLock数据结构

ReentrantReadWriteLock的UML类图如下:
这里写图片描述

从中可以看出:

(01) ReentrantReadWriteLock实现了ReadWriteLock接口。ReadWriteLock是一个读写锁的接口,提供了”获取读锁的readLock()函数” 和 “获取写锁的writeLock()函数”。

(02) ReentrantReadWriteLock中包含:sync对象,读锁readerLock和写锁writerLock。读锁ReadLock和写锁WriteLock都实现了Lock接口。读锁ReadLock和写锁WriteLock中也都分别包含了”Sync对象”,它们的Sync对象和ReentrantReadWriteLock的Sync对象 是一样的,就是通过sync,读锁和写锁实现了对同一个对象的访问。

(03) 和”ReentrantLock”一样,sync是Sync类型;而且,Sync也是一个继承于AQS的抽象类。Sync也包括”公平锁”FairSync和”非公平锁”NonfairSync。sync对象是”FairSync”和”NonfairSync”中的一个,默认是”NonfairSync”。


参考代码(基于JDK1.7.0_40)

ReentrantReadWriteLock的完整源码

/* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * *//* * * * * * * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */package java.util.concurrent.locks;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import java.util.*;/** * An implementation of {@link ReadWriteLock} supporting similar * semantics to {@link ReentrantLock}. * <p>This class has the following properties: * * <ul> * <li><b>Acquisition order</b> * * <p> This class does not impose a reader or writer preference * ordering for lock access.  However, it does support an optional * <em>fairness</em> policy. * * <dl> * <dt><b><i>Non-fair mode (default)</i></b> * <dd>When constructed as non-fair (the default), the order of entry * to the read and write lock is unspecified, subject to reentrancy * constraints.  A nonfair lock that is continuously contended may * indefinitely postpone one or more reader or writer threads, but * will normally have higher throughput than a fair lock. * <p> * * <dt><b><i>Fair mode</i></b> * <dd> When constructed as fair, threads contend for entry using an * approximately arrival-order policy. When the currently held lock * is released either the longest-waiting single writer thread will * be assigned the write lock, or if there is a group of reader threads * waiting longer than all waiting writer threads, that group will be * assigned the read lock. * * <p>A thread that tries to acquire a fair read lock (non-reentrantly) * will block if either the write lock is held, or there is a waiting * writer thread. The thread will not acquire the read lock until * after the oldest currently waiting writer thread has acquired and * released the write lock. Of course, if a waiting writer abandons * its wait, leaving one or more reader threads as the longest waiters * in the queue with the write lock free, then those readers will be * assigned the read lock. * * <p>A thread that tries to acquire a fair write lock (non-reentrantly) * will block unless both the read lock and write lock are free (which * implies there are no waiting threads).  (Note that the non-blocking * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods * do not honor this fair setting and will acquire the lock if it is * possible, regardless of waiting threads.) * <p> * </dl> * * <li><b>Reentrancy</b> * * <p>This lock allows both readers and writers to reacquire read or * write locks in the style of a {@link ReentrantLock}. Non-reentrant * readers are not allowed until all write locks held by the writing * thread have been released. * * <p>Additionally, a writer can acquire the read lock, but not * vice-versa.  Among other applications, reentrancy can be useful * when write locks are held during calls or callbacks to methods that * perform reads under read locks.  If a reader tries to acquire the * write lock it will never succeed. * * <li><b>Lock downgrading</b> * <p>Reentrancy also allows downgrading from the write lock to a read lock, * by acquiring the write lock, then the read lock and then releasing the * write lock. However, upgrading from a read lock to the write lock is * <b>not</b> possible. * * <li><b>Interruption of lock acquisition</b> * <p>The read lock and write lock both support interruption during lock * acquisition. * * <li><b>{@link Condition} support</b> * <p>The write lock provides a {@link Condition} implementation that * behaves in the same way, with respect to the write lock, as the * {@link Condition} implementation provided by * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}. * This {@link Condition} can, of course, only be used with the write lock. * * <p>The read lock does not support a {@link Condition} and * {@code readLock().newCondition()} throws * {@code UnsupportedOperationException}. * * <li><b>Instrumentation</b> * <p>This class supports methods to determine whether locks * are held or contended. These methods are designed for monitoring * system state, not for synchronization control. * </ul> * * <p>Serialization of this class behaves in the same way as built-in * locks: a deserialized lock is in the unlocked state, regardless of * its state when serialized. * * <p><b>Sample usages</b>. Here is a code sketch showing how to perform * lock downgrading after updating a cache (exception handling is * particularly tricky when handling multiple locks in a non-nested * fashion): * * <pre> {@code * class CachedData { *   Object data; *   volatile boolean cacheValid; *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); * *   void processCachedData() { *     rwl.readLock().lock(); *     if (!cacheValid) { *        // Must release read lock before acquiring write lock *        rwl.readLock().unlock(); *        rwl.writeLock().lock(); *        try { *          // Recheck state because another thread might have *          // acquired write lock and changed state before we did. *          if (!cacheValid) { *            data = ... *            cacheValid = true; *          } *          // Downgrade by acquiring read lock before releasing write lock *          rwl.readLock().lock(); *        } finally { *          rwl.writeLock().unlock(); // Unlock write, still hold read *        } *     } * *     try { *       use(data); *     } finally { *       rwl.readLock().unlock(); *     } *   } * }}</pre> * * ReentrantReadWriteLocks can be used to improve concurrency in some * uses of some kinds of Collections. This is typically worthwhile * only when the collections are expected to be large, accessed by * more reader threads than writer threads, and entail operations with * overhead that outweighs synchronization overhead. For example, here * is a class using a TreeMap that is expected to be large and * concurrently accessed. * * <pre>{@code * class RWDictionary { *    private final Map<String, Data> m = new TreeMap<String, Data>(); *    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); *    private final Lock r = rwl.readLock(); *    private final Lock w = rwl.writeLock(); * *    public Data get(String key) { *        r.lock(); *        try { return m.get(key); } *        finally { r.unlock(); } *    } *    public String[] allKeys() { *        r.lock(); *        try { return m.keySet().toArray(); } *        finally { r.unlock(); } *    } *    public Data put(String key, Data value) { *        w.lock(); *        try { return m.put(key, value); } *        finally { w.unlock(); } *    } *    public void clear() { *        w.lock(); *        try { m.clear(); } *        finally { w.unlock(); } *    } * }}</pre> * * <h3>Implementation Notes</h3> * * <p>This lock supports a maximum of 65535 recursive write locks * and 65535 read locks. Attempts to exceed these limits result in * {@link Error} throws from locking methods. * * @since 1.5 * @author Doug Lea * */public class ReentrantReadWriteLock        implements ReadWriteLock, java.io.Serializable {    private static final long serialVersionUID = -6992448646407690164L;    /** Inner class providing readlock */    private final ReentrantReadWriteLock.ReadLock readerLock;    /** Inner class providing writelock */    private final ReentrantReadWriteLock.WriteLock writerLock;    /** Performs all synchronization mechanics */    final Sync sync;    /**     * Creates a new {@code ReentrantReadWriteLock} with     * default (nonfair) ordering properties.     */    public ReentrantReadWriteLock() {        this(false);    }    /**     * Creates a new {@code ReentrantReadWriteLock} with     * the given fairness policy.     *     * @param fair {@code true} if this lock should use a fair ordering policy     */    public ReentrantReadWriteLock(boolean fair) {        sync = fair ? new FairSync() : new NonfairSync();        readerLock = new ReadLock(this);        writerLock = new WriteLock(this);    }    public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }    public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }    /**     * Synchronization implementation for ReentrantReadWriteLock.     * Subclassed into fair and nonfair versions.     */    abstract static class Sync extends AbstractQueuedSynchronizer {        private static final long serialVersionUID = 6317671515068378041L;        /*         * Read vs write count extraction constants and functions.         * Lock state is logically divided into two unsigned shorts:         * The lower one representing the exclusive (writer) lock hold count,         * and the upper the shared (reader) hold count.         */        static final int SHARED_SHIFT   = 16;        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;        /** Returns the number of shared holds represented in count  */        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }        /** Returns the number of exclusive holds represented in count  */        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }        /**         * A counter for per-thread read hold counts.         * Maintained as a ThreadLocal; cached in cachedHoldCounter         */        static final class HoldCounter {            int count = 0;            // Use id, not reference, to avoid garbage retention            final long tid = Thread.currentThread().getId();        }        /**         * ThreadLocal subclass. Easiest to explicitly define for sake         * of deserialization mechanics.         */        static final class ThreadLocalHoldCounter            extends ThreadLocal<HoldCounter> {            public HoldCounter initialValue() {                return new HoldCounter();            }        }        /**         * The number of reentrant read locks held by current thread.         * Initialized only in constructor and readObject.         * Removed whenever a thread's read hold count drops to 0.         */        private transient ThreadLocalHoldCounter readHolds;        /**         * The hold count of the last thread to successfully acquire         * readLock. This saves ThreadLocal lookup in the common case         * where the next thread to release is the last one to         * acquire. This is non-volatile since it is just used         * as a heuristic, and would be great for threads to cache.         *         * <p>Can outlive the Thread for which it is caching the read         * hold count, but avoids garbage retention by not retaining a         * reference to the Thread.         *         * <p>Accessed via a benign data race; relies on the memory         * model's final field and out-of-thin-air guarantees.         */        private transient HoldCounter cachedHoldCounter;        /**         * firstReader is the first thread to have acquired the read lock.         * firstReaderHoldCount is firstReader's hold count.         *         * <p>More precisely, firstReader is the unique thread that last         * changed the shared count from 0 to 1, and has not released the         * read lock since then; null if there is no such thread.         *         * <p>Cannot cause garbage retention unless the thread terminated         * without relinquishing its read locks, since tryReleaseShared         * sets it to null.         *         * <p>Accessed via a benign data race; relies on the memory         * model's out-of-thin-air guarantees for references.         *         * <p>This allows tracking of read holds for uncontended read         * locks to be very cheap.         */        private transient Thread firstReader = null;        private transient int firstReaderHoldCount;        Sync() {            readHolds = new ThreadLocalHoldCounter();            setState(getState()); // ensures visibility of readHolds        }        /*         * Acquires and releases use the same code for fair and         * nonfair locks, but differ in whether/how they allow barging         * when queues are non-empty.         */        /**         * Returns true if the current thread, when trying to acquire         * the read lock, and otherwise eligible to do so, should block         * because of policy for overtaking other waiting threads.         */        abstract boolean readerShouldBlock();        /**         * Returns true if the current thread, when trying to acquire         * the write lock, and otherwise eligible to do so, should block         * because of policy for overtaking other waiting threads.         */        abstract boolean writerShouldBlock();        /*         * Note that tryRelease and tryAcquire can be called by         * Conditions. So it is possible that their arguments contain         * both read and write holds that are all released during a         * condition wait and re-established in tryAcquire.         */        protected final boolean tryRelease(int releases) {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            int nextc = getState() - releases;            boolean free = exclusiveCount(nextc) == 0;            if (free)                setExclusiveOwnerThread(null);            setState(nextc);            return free;        }        protected final boolean tryAcquire(int acquires) {            /*             * Walkthrough:             * 1. If read count nonzero or write count nonzero             *    and owner is a different thread, fail.             * 2. If count would saturate, fail. (This can only             *    happen if count is already nonzero.)             * 3. Otherwise, this thread is eligible for lock if             *    it is either a reentrant acquire or             *    queue policy allows it. If so, update state             *    and set owner.             */            Thread current = Thread.currentThread();            int c = getState();            int w = exclusiveCount(c);            if (c != 0) {                // (Note: if c != 0 and w == 0 then shared count != 0)                if (w == 0 || current != getExclusiveOwnerThread())                    return false;                if (w + exclusiveCount(acquires) > MAX_COUNT)                    throw new Error("Maximum lock count exceeded");                // Reentrant acquire                setState(c + acquires);                return true;            }            if (writerShouldBlock() ||                !compareAndSetState(c, c + acquires))                return false;            setExclusiveOwnerThread(current);            return true;        }        protected final boolean tryReleaseShared(int unused) {            Thread current = Thread.currentThread();            if (firstReader == current) {                // assert firstReaderHoldCount > 0;                if (firstReaderHoldCount == 1)                    firstReader = null;                else                    firstReaderHoldCount--;            } else {                HoldCounter rh = cachedHoldCounter;                if (rh == null || rh.tid != current.getId())                    rh = readHolds.get();                int count = rh.count;                if (count <= 1) {                    readHolds.remove();                    if (count <= 0)                        throw unmatchedUnlockException();                }                --rh.count;            }            for (;;) {                int c = getState();                int nextc = c - SHARED_UNIT;                if (compareAndSetState(c, nextc))                    // Releasing the read lock has no effect on readers,                    // but it may allow waiting writers to proceed if                    // both read and write locks are now free.                    return nextc == 0;            }        }        private IllegalMonitorStateException unmatchedUnlockException() {            return new IllegalMonitorStateException(                "attempt to unlock read lock, not locked by current thread");        }        protected final int tryAcquireShared(int unused) {            /*             * Walkthrough:             * 1. If write lock held by another thread, fail.             * 2. Otherwise, this thread is eligible for             *    lock wrt state, so ask if it should block             *    because of queue policy. If not, try             *    to grant by CASing state and updating count.             *    Note that step does not check for reentrant             *    acquires, which is postponed to full version             *    to avoid having to check hold count in             *    the more typical non-reentrant case.             * 3. If step 2 fails either because thread             *    apparently not eligible or CAS fails or count             *    saturated, chain to version with full retry loop.             */            Thread current = Thread.currentThread();            int c = getState();            if (exclusiveCount(c) != 0 &&                getExclusiveOwnerThread() != current)                return -1;            int r = sharedCount(c);            if (!readerShouldBlock() &&                r < MAX_COUNT &&                compareAndSetState(c, c + SHARED_UNIT)) {                if (r == 0) {                    firstReader = current;                    firstReaderHoldCount = 1;                } else if (firstReader == current) {                    firstReaderHoldCount++;                } else {                    HoldCounter rh = cachedHoldCounter;                    if (rh == null || rh.tid != current.getId())                        cachedHoldCounter = rh = readHolds.get();                    else if (rh.count == 0)                        readHolds.set(rh);                    rh.count++;                }                return 1;            }            return fullTryAcquireShared(current);        }        /**         * Full version of acquire for reads, that handles CAS misses         * and reentrant reads not dealt with in tryAcquireShared.         */        final int fullTryAcquireShared(Thread current) {            /*             * This code is in part redundant with that in             * tryAcquireShared but is simpler overall by not             * complicating tryAcquireShared with interactions between             * retries and lazily reading hold counts.             */            HoldCounter rh = null;            for (;;) {                int c = getState();                if (exclusiveCount(c) != 0) {                    if (getExclusiveOwnerThread() != current)                        return -1;                    // else we hold the exclusive lock; blocking here                    // would cause deadlock.                } else if (readerShouldBlock()) {                    // Make sure we're not acquiring read lock reentrantly                    if (firstReader == current) {                        // assert firstReaderHoldCount > 0;                    } else {                        if (rh == null) {                            rh = cachedHoldCounter;                            if (rh == null || rh.tid != current.getId()) {                                rh = readHolds.get();                                if (rh.count == 0)                                    readHolds.remove();                            }                        }                        if (rh.count == 0)                            return -1;                    }                }                if (sharedCount(c) == MAX_COUNT)                    throw new Error("Maximum lock count exceeded");                if (compareAndSetState(c, c + SHARED_UNIT)) {                    if (sharedCount(c) == 0) {                        firstReader = current;                        firstReaderHoldCount = 1;                    } else if (firstReader == current) {                        firstReaderHoldCount++;                    } else {                        if (rh == null)                            rh = cachedHoldCounter;                        if (rh == null || rh.tid != current.getId())                            rh = readHolds.get();                        else if (rh.count == 0)                            readHolds.set(rh);                        rh.count++;                        cachedHoldCounter = rh; // cache for release                    }                    return 1;                }            }        }        /**         * Performs tryLock for write, enabling barging in both modes.         * This is identical in effect to tryAcquire except for lack         * of calls to writerShouldBlock.         */        final boolean tryWriteLock() {            Thread current = Thread.currentThread();            int c = getState();            if (c != 0) {                int w = exclusiveCount(c);                if (w == 0 || current != getExclusiveOwnerThread())                    return false;                if (w == MAX_COUNT)                    throw new Error("Maximum lock count exceeded");            }            if (!compareAndSetState(c, c + 1))                return false;            setExclusiveOwnerThread(current);            return true;        }        /**         * Performs tryLock for read, enabling barging in both modes.         * This is identical in effect to tryAcquireShared except for         * lack of calls to readerShouldBlock.         */        final boolean tryReadLock() {            Thread current = Thread.currentThread();            for (;;) {                int c = getState();                if (exclusiveCount(c) != 0 &&                    getExclusiveOwnerThread() != current)                    return false;                int r = sharedCount(c);                if (r == MAX_COUNT)                    throw new Error("Maximum lock count exceeded");                if (compareAndSetState(c, c + SHARED_UNIT)) {                    if (r == 0) {                        firstReader = current;                        firstReaderHoldCount = 1;                    } else if (firstReader == current) {                        firstReaderHoldCount++;                    } else {                        HoldCounter rh = cachedHoldCounter;                        if (rh == null || rh.tid != current.getId())                            cachedHoldCounter = rh = readHolds.get();                        else if (rh.count == 0)                            readHolds.set(rh);                        rh.count++;                    }                    return true;                }            }        }        protected final boolean isHeldExclusively() {            // While we must in general read state before owner,            // we don't need to do so to check if current thread is owner            return getExclusiveOwnerThread() == Thread.currentThread();        }        // Methods relayed to outer class        final ConditionObject newCondition() {            return new ConditionObject();        }        final Thread getOwner() {            // Must read state before owner to ensure memory consistency            return ((exclusiveCount(getState()) == 0) ?                    null :                    getExclusiveOwnerThread());        }        final int getReadLockCount() {            return sharedCount(getState());        }        final boolean isWriteLocked() {            return exclusiveCount(getState()) != 0;        }        final int getWriteHoldCount() {            return isHeldExclusively() ? exclusiveCount(getState()) : 0;        }        final int getReadHoldCount() {            if (getReadLockCount() == 0)                return 0;            Thread current = Thread.currentThread();            if (firstReader == current)                return firstReaderHoldCount;            HoldCounter rh = cachedHoldCounter;            if (rh != null && rh.tid == current.getId())                return rh.count;            int count = readHolds.get().count;            if (count == 0) readHolds.remove();            return count;        }        /**         * Reconstitute this lock instance from a stream         * @param s the stream         */        private void readObject(java.io.ObjectInputStream s)            throws java.io.IOException, ClassNotFoundException {            s.defaultReadObject();            readHolds = new ThreadLocalHoldCounter();            setState(0); // reset to unlocked state        }        final int getCount() { return getState(); }    }    /**     * Nonfair version of Sync     */    static final class NonfairSync extends Sync {        private static final long serialVersionUID = -8159625535654395037L;        final boolean writerShouldBlock() {            return false; // writers can always barge        }        final boolean readerShouldBlock() {            /* As a heuristic to avoid indefinite writer starvation,             * block if the thread that momentarily appears to be head             * of queue, if one exists, is a waiting writer.  This is             * only a probabilistic effect since a new reader will not             * block if there is a waiting writer behind other enabled             * readers that have not yet drained from the queue.             */            return apparentlyFirstQueuedIsExclusive();        }    }    /**     * Fair version of Sync     */    static final class FairSync extends Sync {        private static final long serialVersionUID = -2274990926593161451L;        final boolean writerShouldBlock() {            return hasQueuedPredecessors();        }        final boolean readerShouldBlock() {            return hasQueuedPredecessors();        }    }    /**     * The lock returned by method {@link ReentrantReadWriteLock#readLock}.     */    public static class ReadLock implements Lock, java.io.Serializable {        private static final long serialVersionUID = -5992448646407690164L;        private final Sync sync;        /**         * Constructor for use by subclasses         *         * @param lock the outer lock object         * @throws NullPointerException if the lock is null         */        protected ReadLock(ReentrantReadWriteLock lock) {            sync = lock.sync;        }        /**         * Acquires the read lock.         *         * <p>Acquires the read lock if the write lock is not held by         * another thread and returns immediately.         *         * <p>If the write lock is held by another thread then         * the current thread becomes disabled for thread scheduling         * purposes and lies dormant until the read lock has been acquired.         */        public void lock() {            sync.acquireShared(1);        }        /**         * Acquires the read lock unless the current thread is         * {@linkplain Thread#interrupt interrupted}.         *         * <p>Acquires the read lock if the write lock is not held         * by another thread and returns immediately.         *         * <p>If the write lock is held by another thread then the         * current thread becomes disabled for thread scheduling         * purposes and lies dormant until one of two things happens:         *         * <ul>         *         * <li>The read lock is acquired by the current thread; or         *         * <li>Some other thread {@linkplain Thread#interrupt interrupts}         * the current thread.         *         * </ul>         *         * <p>If the current thread:         *         * <ul>         *         * <li>has its interrupted status set on entry to this method; or         *         * <li>is {@linkplain Thread#interrupt interrupted} while         * acquiring the read lock,         *         * </ul>         *         * then {@link InterruptedException} is thrown and the current         * thread's interrupted status is cleared.         *         * <p>In this implementation, as this method is an explicit         * interruption point, preference is given to responding to         * the interrupt over normal or reentrant acquisition of the         * lock.         *         * @throws InterruptedException if the current thread is interrupted         */        public void lockInterruptibly() throws InterruptedException {            sync.acquireSharedInterruptibly(1);        }        /**         * Acquires the read lock only if the write lock is not held by         * another thread at the time of invocation.         *         * <p>Acquires the read lock if the write lock is not held by         * another thread and returns immediately with the value         * {@code true}. Even when this lock has been set to use a         * fair ordering policy, a call to {@code tryLock()}         * <em>will</em> immediately acquire the read lock if it is         * available, whether or not other threads are currently         * waiting for the read lock.  This &quot;barging&quot; behavior         * can be useful in certain circumstances, even though it         * breaks fairness. If you want to honor the fairness setting         * for this lock, then use {@link #tryLock(long, TimeUnit)         * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent         * (it also detects interruption).         *         * <p>If the write lock is held by another thread then         * this method will return immediately with the value         * {@code false}.         *         * @return {@code true} if the read lock was acquired         */        public  boolean tryLock() {            return sync.tryReadLock();        }        /**         * Acquires the read lock if the write lock is not held by         * another thread within the given waiting time and the         * current thread has not been {@linkplain Thread#interrupt         * interrupted}.         *         * <p>Acquires the read lock if the write lock is not held by         * another thread and returns immediately with the value         * {@code true}. If this lock has been set to use a fair         * ordering policy then an available lock <em>will not</em> be         * acquired if any other threads are waiting for the         * lock. This is in contrast to the {@link #tryLock()}         * method. If you want a timed {@code tryLock} that does         * permit barging on a fair lock then combine the timed and         * un-timed forms together:         *         * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }         * </pre>         *         * <p>If the write lock is held by another thread then the         * current thread becomes disabled for thread scheduling         * purposes and lies dormant until one of three things happens:         *         * <ul>         *         * <li>The read lock is acquired by the current thread; or         *         * <li>Some other thread {@linkplain Thread#interrupt interrupts}         * the current thread; or         *         * <li>The specified waiting time elapses.         *         * </ul>         *         * <p>If the read lock is acquired then the value {@code true} is         * returned.         *         * <p>If the current thread:         *         * <ul>         *         * <li>has its interrupted status set on entry to this method; or         *         * <li>is {@linkplain Thread#interrupt interrupted} while         * acquiring the read lock,         *         * </ul> then {@link InterruptedException} is thrown and the         * current thread's interrupted status is cleared.         *         * <p>If the specified waiting time elapses then the value         * {@code false} is returned.  If the time is less than or         * equal to zero, the method will not wait at all.         *         * <p>In this implementation, as this method is an explicit         * interruption point, preference is given to responding to         * the interrupt over normal or reentrant acquisition of the         * lock, and over reporting the elapse of the waiting time.         *         * @param timeout the time to wait for the read lock         * @param unit the time unit of the timeout argument         * @return {@code true} if the read lock was acquired         * @throws InterruptedException if the current thread is interrupted         * @throws NullPointerException if the time unit is null         *         */        public boolean tryLock(long timeout, TimeUnit unit)                throws InterruptedException {            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));        }        /**         * Attempts to release this lock.         *         * <p> If the number of readers is now zero then the lock         * is made available for write lock attempts.         */        public  void unlock() {            sync.releaseShared(1);        }        /**         * Throws {@code UnsupportedOperationException} because         * {@code ReadLocks} do not support conditions.         *         * @throws UnsupportedOperationException always         */        public Condition newCondition() {            throw new UnsupportedOperationException();        }        /**         * Returns a string identifying this lock, as well as its lock state.         * The state, in brackets, includes the String {@code "Read locks ="}         * followed by the number of held read locks.         *         * @return a string identifying this lock, as well as its lock state         */        public String toString() {            int r = sync.getReadLockCount();            return super.toString() +                "[Read locks = " + r + "]";        }    }    /**     * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.     */    public static class WriteLock implements Lock, java.io.Serializable {        private static final long serialVersionUID = -4992448646407690164L;        private final Sync sync;        /**         * Constructor for use by subclasses         *         * @param lock the outer lock object         * @throws NullPointerException if the lock is null         */        protected WriteLock(ReentrantReadWriteLock lock) {            sync = lock.sync;        }        /**         * Acquires the write lock.         *         * <p>Acquires the write lock if neither the read nor write lock         * are held by another thread         * and returns immediately, setting the write lock hold count to         * one.         *         * <p>If the current thread already holds the write lock then the         * hold count is incremented by one and the method returns         * immediately.         *         * <p>If the lock is held by another thread then the current         * thread becomes disabled for thread scheduling purposes and         * lies dormant until the write lock has been acquired, at which         * time the write lock hold count is set to one.         */        public void lock() {            sync.acquire(1);        }        /**         * Acquires the write lock unless the current thread is         * {@linkplain Thread#interrupt interrupted}.         *         * <p>Acquires the write lock if neither the read nor write lock         * are held by another thread         * and returns immediately, setting the write lock hold count to         * one.         *         * <p>If the current thread already holds this lock then the         * hold count is incremented by one and the method returns         * immediately.         *         * <p>If the lock is held by another thread then the current         * thread becomes disabled for thread scheduling purposes and         * lies dormant until one of two things happens:         *         * <ul>         *         * <li>The write lock is acquired by the current thread; or         *         * <li>Some other thread {@linkplain Thread#interrupt interrupts}         * the current thread.         *         * </ul>         *         * <p>If the write lock is acquired by the current thread then the         * lock hold count is set to one.         *         * <p>If the current thread:         *         * <ul>         *         * <li>has its interrupted status set on entry to this method;         * or         *         * <li>is {@linkplain Thread#interrupt interrupted} while         * acquiring the write lock,         *         * </ul>         *         * then {@link InterruptedException} is thrown and the current         * thread's interrupted status is cleared.         *         * <p>In this implementation, as this method is an explicit         * interruption point, preference is given to responding to         * the interrupt over normal or reentrant acquisition of the         * lock.         *         * @throws InterruptedException if the current thread is interrupted         */        public void lockInterruptibly() throws InterruptedException {            sync.acquireInterruptibly(1);        }        /**         * Acquires the write lock only if it is not held by another thread         * at the time of invocation.         *         * <p>Acquires the write lock if neither the read nor write lock         * are held by another thread         * and returns immediately with the value {@code true},         * setting the write lock hold count to one. Even when this lock has         * been set to use a fair ordering policy, a call to         * {@code tryLock()} <em>will</em> immediately acquire the         * lock if it is available, whether or not other threads are         * currently waiting for the write lock.  This &quot;barging&quot;         * behavior can be useful in certain circumstances, even         * though it breaks fairness. If you want to honor the         * fairness setting for this lock, then use {@link         * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }         * which is almost equivalent (it also detects interruption).         *         * <p> If the current thread already holds this lock then the         * hold count is incremented by one and the method returns         * {@code true}.         *         * <p>If the lock is held by another thread then this method         * will return immediately with the value {@code false}.         *         * @return {@code true} if the lock was free and was acquired         * by the current thread, or the write lock was already held         * by the current thread; and {@code false} otherwise.         */        public boolean tryLock( ) {            return sync.tryWriteLock();        }        /**         * Acquires the write lock if it is not held by another thread         * within the given waiting time and the current thread has         * not been {@linkplain Thread#interrupt interrupted}.         *         * <p>Acquires the write lock if neither the read nor write lock         * are held by another thread         * and returns immediately with the value {@code true},         * setting the write lock hold count to one. If this lock has been         * set to use a fair ordering policy then an available lock         * <em>will not</em> be acquired if any other threads are         * waiting for the write lock. This is in contrast to the {@link         * #tryLock()} method. If you want a timed {@code tryLock}         * that does permit barging on a fair lock then combine the         * timed and un-timed forms together:         *         * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }         * </pre>         *         * <p>If the current thread already holds this lock then the         * hold count is incremented by one and the method returns         * {@code true}.         *         * <p>If the lock is held by another thread then the current         * thread becomes disabled for thread scheduling purposes and         * lies dormant until one of three things happens:         *         * <ul>         *         * <li>The write lock is acquired by the current thread; or         *         * <li>Some other thread {@linkplain Thread#interrupt interrupts}         * the current thread; or         *         * <li>The specified waiting time elapses         *         * </ul>         *         * <p>If the write lock is acquired then the value {@code true} is         * returned and the write lock hold count is set to one.         *         * <p>If the current thread:         *         * <ul>         *         * <li>has its interrupted status set on entry to this method;         * or         *         * <li>is {@linkplain Thread#interrupt interrupted} while         * acquiring the write lock,         *         * </ul>         *         * then {@link InterruptedException} is thrown and the current         * thread's interrupted status is cleared.         *         * <p>If the specified waiting time elapses then the value         * {@code false} is returned.  If the time is less than or         * equal to zero, the method will not wait at all.         *         * <p>In this implementation, as this method is an explicit         * interruption point, preference is given to responding to         * the interrupt over normal or reentrant acquisition of the         * lock, and over reporting the elapse of the waiting time.         *         * @param timeout the time to wait for the write lock         * @param unit the time unit of the timeout argument         *         * @return {@code true} if the lock was free and was acquired         * by the current thread, or the write lock was already held by the         * current thread; and {@code false} if the waiting time         * elapsed before the lock could be acquired.         *         * @throws InterruptedException if the current thread is interrupted         * @throws NullPointerException if the time unit is null         *         */        public boolean tryLock(long timeout, TimeUnit unit)                throws InterruptedException {            return sync.tryAcquireNanos(1, unit.toNanos(timeout));        }        /**         * Attempts to release this lock.         *         * <p>If the current thread is the holder of this lock then         * the hold count is decremented. If the hold count is now         * zero then the lock is released.  If the current thread is         * not the holder of this lock then {@link         * IllegalMonitorStateException} is thrown.         *         * @throws IllegalMonitorStateException if the current thread does not         * hold this lock.         */        public void unlock() {            sync.release(1);        }        /**         * Returns a {@link Condition} instance for use with this         * {@link Lock} instance.         * <p>The returned {@link Condition} instance supports the same         * usages as do the {@link Object} monitor methods ({@link         * Object#wait() wait}, {@link Object#notify notify}, and {@link         * Object#notifyAll notifyAll}) when used with the built-in         * monitor lock.         *         * <ul>         *         * <li>If this write lock is not held when any {@link         * Condition} method is called then an {@link         * IllegalMonitorStateException} is thrown.  (Read locks are         * held independently of write locks, so are not checked or         * affected. However it is essentially always an error to         * invoke a condition waiting method when the current thread         * has also acquired read locks, since other threads that         * could unblock it will not be able to acquire the write         * lock.)         *         * <li>When the condition {@linkplain Condition#await() waiting}         * methods are called the write lock is released and, before         * they return, the write lock is reacquired and the lock hold         * count restored to what it was when the method was called.         *         * <li>If a thread is {@linkplain Thread#interrupt interrupted} while         * waiting then the wait will terminate, an {@link         * InterruptedException} will be thrown, and the thread's         * interrupted status will be cleared.         *         * <li> Waiting threads are signalled in FIFO order.         *         * <li>The ordering of lock reacquisition for threads returning         * from waiting methods is the same as for threads initially         * acquiring the lock, which is in the default case not specified,         * but for <em>fair</em> locks favors those threads that have been         * waiting the longest.         *         * </ul>         *         * @return the Condition object         */        public Condition newCondition() {            return sync.newCondition();        }        /**         * Returns a string identifying this lock, as well as its lock         * state.  The state, in brackets includes either the String         * {@code "Unlocked"} or the String {@code "Locked by"}         * followed by the {@linkplain Thread#getName name} of the owning thread.         *         * @return a string identifying this lock, as well as its lock state         */        public String toString() {            Thread o = sync.getOwner();            return super.toString() + ((o == null) ?                                       "[Unlocked]" :                                       "[Locked by thread " + o.getName() + "]");        }        /**         * Queries if this write lock is held by the current thread.         * Identical in effect to {@link         * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.         *         * @return {@code true} if the current thread holds this lock and         *         {@code false} otherwise         * @since 1.6         */        public boolean isHeldByCurrentThread() {            return sync.isHeldExclusively();        }        /**         * Queries the number of holds on this write lock by the current         * thread.  A thread has a hold on a lock for each lock action         * that is not matched by an unlock action.  Identical in effect         * to {@link ReentrantReadWriteLock#getWriteHoldCount}.         *         * @return the number of holds on this lock by the current thread,         *         or zero if this lock is not held by the current thread         * @since 1.6         */        public int getHoldCount() {            return sync.getWriteHoldCount();        }    }    // Instrumentation and status    /**     * Returns {@code true} if this lock has fairness set true.     *     * @return {@code true} if this lock has fairness set true     */    public final boolean isFair() {        return sync instanceof FairSync;    }    /**     * Returns the thread that currently owns the write lock, or     * {@code null} if not owned. When this method is called by a     * thread that is not the owner, the return value reflects a     * best-effort approximation of current lock status. For example,     * the owner may be momentarily {@code null} even if there are     * threads trying to acquire the lock but have not yet done so.     * This method is designed to facilitate construction of     * subclasses that provide more extensive lock monitoring     * facilities.     *     * @return the owner, or {@code null} if not owned     */    protected Thread getOwner() {        return sync.getOwner();    }    /**     * Queries the number of read locks held for this lock. This     * method is designed for use in monitoring system state, not for     * synchronization control.     * @return the number of read locks held.     */    public int getReadLockCount() {        return sync.getReadLockCount();    }    /**     * Queries if the write lock is held by any thread. This method is     * designed for use in monitoring system state, not for     * synchronization control.     *     * @return {@code true} if any thread holds the write lock and     *         {@code false} otherwise     */    public boolean isWriteLocked() {        return sync.isWriteLocked();    }    /**     * Queries if the write lock is held by the current thread.     *     * @return {@code true} if the current thread holds the write lock and     *         {@code false} otherwise     */    public boolean isWriteLockedByCurrentThread() {        return sync.isHeldExclusively();    }    /**     * Queries the number of reentrant write holds on this lock by the     * current thread.  A writer thread has a hold on a lock for     * each lock action that is not matched by an unlock action.     *     * @return the number of holds on the write lock by the current thread,     *         or zero if the write lock is not held by the current thread     */    public int getWriteHoldCount() {        return sync.getWriteHoldCount();    }    /**     * Queries the number of reentrant read holds on this lock by the     * current thread.  A reader thread has a hold on a lock for     * each lock action that is not matched by an unlock action.     *     * @return the number of holds on the read lock by the current thread,     *         or zero if the read lock is not held by the current thread     * @since 1.6     */    public int getReadHoldCount() {        return sync.getReadHoldCount();    }    /**     * Returns a collection containing threads that may be waiting to     * acquire the write lock.  Because the actual set of threads may     * change dynamically while constructing this result, the returned     * collection is only a best-effort estimate.  The elements of the     * returned collection are in no particular order.  This method is     * designed to facilitate construction of subclasses that provide     * more extensive lock monitoring facilities.     *     * @return the collection of threads     */    protected Collection<Thread> getQueuedWriterThreads() {        return sync.getExclusiveQueuedThreads();    }    /**     * Returns a collection containing threads that may be waiting to     * acquire the read lock.  Because the actual set of threads may     * change dynamically while constructing this result, the returned     * collection is only a best-effort estimate.  The elements of the     * returned collection are in no particular order.  This method is     * designed to facilitate construction of subclasses that provide     * more extensive lock monitoring facilities.     *     * @return the collection of threads     */    protected Collection<Thread> getQueuedReaderThreads() {        return sync.getSharedQueuedThreads();    }    /**     * Queries whether any threads are waiting to acquire the read or     * write lock. Note that because cancellations may occur at any     * time, a {@code true} return does not guarantee that any other     * thread will ever acquire a lock.  This method is designed     * primarily for use in monitoring of the system state.     *     * @return {@code true} if there may be other threads waiting to     *         acquire the lock     */    public final boolean hasQueuedThreads() {        return sync.hasQueuedThreads();    }    /**     * Queries whether the given thread is waiting to acquire either     * the read or write lock. Note that because cancellations may     * occur at any time, a {@code true} return does not guarantee     * that this thread will ever acquire a lock.  This method is     * designed primarily for use in monitoring of the system state.     *     * @param thread the thread     * @return {@code true} if the given thread is queued waiting for this lock     * @throws NullPointerException if the thread is null     */    public final boolean hasQueuedThread(Thread thread) {        return sync.isQueued(thread);    }    /**     * Returns an estimate of the number of threads waiting to acquire     * either the read or write lock.  The value is only an estimate     * because the number of threads may change dynamically while this     * method traverses internal data structures.  This method is     * designed for use in monitoring of the system state, not for     * synchronization control.     *     * @return the estimated number of threads waiting for this lock     */    public final int getQueueLength() {        return sync.getQueueLength();    }    /**     * Returns a collection containing threads that may be waiting to     * acquire either the read or write lock.  Because the actual set     * of threads may change dynamically while constructing this     * result, the returned collection is only a best-effort estimate.     * The elements of the returned collection are in no particular     * order.  This method is designed to facilitate construction of     * subclasses that provide more extensive monitoring facilities.     *     * @return the collection of threads     */    protected Collection<Thread> getQueuedThreads() {        return sync.getQueuedThreads();    }    /**     * Queries whether any threads are waiting on the given condition     * associated with the write lock. Note that because timeouts and     * interrupts may occur at any time, a {@code true} return does     * not guarantee that a future {@code signal} will awaken any     * threads.  This method is designed primarily for use in     * monitoring of the system state.     *     * @param condition the condition     * @return {@code true} if there are any waiting threads     * @throws IllegalMonitorStateException if this lock is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this lock     * @throws NullPointerException if the condition is null     */    public boolean hasWaiters(Condition condition) {        if (condition == null)            throw new NullPointerException();        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))            throw new IllegalArgumentException("not owner");        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);    }    /**     * Returns an estimate of the number of threads waiting on the     * given condition associated with the write lock. Note that because     * timeouts and interrupts may occur at any time, the estimate     * serves only as an upper bound on the actual number of waiters.     * This method is designed for use in monitoring of the system     * state, not for synchronization control.     *     * @param condition the condition     * @return the estimated number of waiting threads     * @throws IllegalMonitorStateException if this lock is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this lock     * @throws NullPointerException if the condition is null     */    public int getWaitQueueLength(Condition condition) {        if (condition == null)            throw new NullPointerException();        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))            throw new IllegalArgumentException("not owner");        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);    }    /**     * Returns a collection containing those threads that may be     * waiting on the given condition associated with the write lock.     * Because the actual set of threads may change dynamically while     * constructing this result, the returned collection is only a     * best-effort estimate. The elements of the returned collection     * are in no particular order.  This method is designed to     * facilitate construction of subclasses that provide more     * extensive condition monitoring facilities.     *     * @param condition the condition     * @return the collection of threads     * @throws IllegalMonitorStateException if this lock is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this lock     * @throws NullPointerException if the condition is null     */    protected Collection<Thread> getWaitingThreads(Condition condition) {        if (condition == null)            throw new NullPointerException();        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))            throw new IllegalArgumentException("not owner");        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);    }    /**     * Returns a string identifying this lock, as well as its lock state.     * The state, in brackets, includes the String {@code "Write locks ="}     * followed by the number of reentrantly held write locks, and the     * String {@code "Read locks ="} followed by the number of held     * read locks.     *     * @return a string identifying this lock, as well as its lock state     */    public String toString() {        int c = sync.getCount();        int w = Sync.exclusiveCount(c);        int r = Sync.sharedCount(c);        return super.toString() +            "[Write locks = " + w + ", Read locks = " + r + "]";    }}

AQS的完整源码

/* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * *//* * * * * * * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */package java.util.concurrent.locks;import java.util.*;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import sun.misc.Unsafe;/** * Provides a framework for implementing blocking locks and related * synchronizers (semaphores, events, etc) that rely on * first-in-first-out (FIFO) wait queues.  This class is designed to * be a useful basis for most kinds of synchronizers that rely on a * single atomic <tt>int</tt> value to represent state. Subclasses * must define the protected methods that change this state, and which * define what that state means in terms of this object being acquired * or released.  Given these, the other methods in this class carry * out all queuing and blocking mechanics. Subclasses can maintain * other state fields, but only the atomically updated <tt>int</tt> * value manipulated using methods {@link #getState}, {@link * #setState} and {@link #compareAndSetState} is tracked with respect * to synchronization. * * <p>Subclasses should be defined as non-public internal helper * classes that are used to implement the synchronization properties * of their enclosing class.  Class * <tt>AbstractQueuedSynchronizer</tt> does not implement any * synchronization interface.  Instead it defines methods such as * {@link #acquireInterruptibly} that can be invoked as * appropriate by concrete locks and related synchronizers to * implement their public methods. * * <p>This class supports either or both a default <em>exclusive</em> * mode and a <em>shared</em> mode. When acquired in exclusive mode, * attempted acquires by other threads cannot succeed. Shared mode * acquires by multiple threads may (but need not) succeed. This class * does not &quot;understand&quot; these differences except in the * mechanical sense that when a shared mode acquire succeeds, the next * waiting thread (if one exists) must also determine whether it can * acquire as well. Threads waiting in the different modes share the * same FIFO queue. Usually, implementation subclasses support only * one of these modes, but both can come into play for example in a * {@link ReadWriteLock}. Subclasses that support only exclusive or * only shared modes need not define the methods supporting the unused mode. * * <p>This class defines a nested {@link ConditionObject} class that * can be used as a {@link Condition} implementation by subclasses * supporting exclusive mode for which method {@link * #isHeldExclusively} reports whether synchronization is exclusively * held with respect to the current thread, method {@link #release} * invoked with the current {@link #getState} value fully releases * this object, and {@link #acquire}, given this saved state value, * eventually restores this object to its previous acquired state.  No * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a * condition, so if this constraint cannot be met, do not use it.  The * behavior of {@link ConditionObject} depends of course on the * semantics of its synchronizer implementation. * * <p>This class provides inspection, instrumentation, and monitoring * methods for the internal queue, as well as similar methods for * condition objects. These can be exported as desired into classes * using an <tt>AbstractQueuedSynchronizer</tt> for their * synchronization mechanics. * * <p>Serialization of this class stores only the underlying atomic * integer maintaining state, so deserialized objects have empty * thread queues. Typical subclasses requiring serializability will * define a <tt>readObject</tt> method that restores this to a known * initial state upon deserialization. * * <h3>Usage</h3> * * <p>To use this class as the basis of a synchronizer, redefine the * following methods, as applicable, by inspecting and/or modifying * the synchronization state using {@link #getState}, {@link * #setState} and/or {@link #compareAndSetState}: * * <ul> * <li> {@link #tryAcquire} * <li> {@link #tryRelease} * <li> {@link #tryAcquireShared} * <li> {@link #tryReleaseShared} * <li> {@link #isHeldExclusively} *</ul> * * Each of these methods by default throws {@link * UnsupportedOperationException}.  Implementations of these methods * must be internally thread-safe, and should in general be short and * not block. Defining these methods is the <em>only</em> supported * means of using this class. All other methods are declared * <tt>final</tt> because they cannot be independently varied. * * <p>You may also find the inherited methods from {@link * AbstractOwnableSynchronizer} useful to keep track of the thread * owning an exclusive synchronizer.  You are encouraged to use them * -- this enables monitoring and diagnostic tools to assist users in * determining which threads hold locks. * * <p>Even though this class is based on an internal FIFO queue, it * does not automatically enforce FIFO acquisition policies.  The core * of exclusive synchronization takes the form: * * <pre> * Acquire: *     while (!tryAcquire(arg)) { *        <em>enqueue thread if it is not already queued</em>; *        <em>possibly block current thread</em>; *     } * * Release: *     if (tryRelease(arg)) *        <em>unblock the first queued thread</em>; * </pre> * * (Shared mode is similar but may involve cascading signals.) * * <p><a name="barging">Because checks in acquire are invoked before * enqueuing, a newly acquiring thread may <em>barge</em> ahead of * others that are blocked and queued.  However, you can, if desired, * define <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to * disable barging by internally invoking one or more of the inspection * methods, thereby providing a <em>fair</em> FIFO acquisition order. * In particular, most fair synchronizers can define <tt>tryAcquire</tt> * to return <tt>false</tt> if {@link #hasQueuedPredecessors} (a method * specifically designed to be used by fair synchronizers) returns * <tt>true</tt>.  Other variations are possible. * * <p>Throughput and scalability are generally highest for the * default barging (also known as <em>greedy</em>, * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy. * While this is not guaranteed to be fair or starvation-free, earlier * queued threads are allowed to recontend before later queued * threads, and each recontention has an unbiased chance to succeed * against incoming threads.  Also, while acquires do not * &quot;spin&quot; in the usual sense, they may perform multiple * invocations of <tt>tryAcquire</tt> interspersed with other * computations before blocking.  This gives most of the benefits of * spins when exclusive synchronization is only briefly held, without * most of the liabilities when it isn't. If so desired, you can * augment this by preceding calls to acquire methods with * "fast-path" checks, possibly prechecking {@link #hasContended} * and/or {@link #hasQueuedThreads} to only do so if the synchronizer * is likely not to be contended. * * <p>This class provides an efficient and scalable basis for * synchronization in part by specializing its range of use to * synchronizers that can rely on <tt>int</tt> state, acquire, and * release parameters, and an internal FIFO wait queue. When this does * not suffice, you can build synchronizers from a lower level using * {@link java.util.concurrent.atomic atomic} classes, your own custom * {@link java.util.Queue} classes, and {@link LockSupport} blocking * support. * * <h3>Usage Examples</h3> * * <p>Here is a non-reentrant mutual exclusion lock class that uses * the value zero to represent the unlocked state, and one to * represent the locked state. While a non-reentrant lock * does not strictly require recording of the current owner * thread, this class does so anyway to make usage easier to monitor. * It also supports conditions and exposes * one of the instrumentation methods: * * <pre> * class Mutex implements Lock, java.io.Serializable { * *   // Our internal helper class *   private static class Sync extends AbstractQueuedSynchronizer { *     // Report whether in locked state *     protected boolean isHeldExclusively() { *       return getState() == 1; *     } * *     // Acquire the lock if state is zero *     public boolean tryAcquire(int acquires) { *       assert acquires == 1; // Otherwise unused *       if (compareAndSetState(0, 1)) { *         setExclusiveOwnerThread(Thread.currentThread()); *         return true; *       } *       return false; *     } * *     // Release the lock by setting state to zero *     protected boolean tryRelease(int releases) { *       assert releases == 1; // Otherwise unused *       if (getState() == 0) throw new IllegalMonitorStateException(); *       setExclusiveOwnerThread(null); *       setState(0); *       return true; *     } * *     // Provide a Condition *     Condition newCondition() { return new ConditionObject(); } * *     // Deserialize properly *     private void readObject(ObjectInputStream s) *         throws IOException, ClassNotFoundException { *       s.defaultReadObject(); *       setState(0); // reset to unlocked state *     } *   } * *   // The sync object does all the hard work. We just forward to it. *   private final Sync sync = new Sync(); * *   public void lock()                { sync.acquire(1); } *   public boolean tryLock()          { return sync.tryAcquire(1); } *   public void unlock()              { sync.release(1); } *   public Condition newCondition()   { return sync.newCondition(); } *   public boolean isLocked()         { return sync.isHeldExclusively(); } *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } *   public void lockInterruptibly() throws InterruptedException { *     sync.acquireInterruptibly(1); *   } *   public boolean tryLock(long timeout, TimeUnit unit) *       throws InterruptedException { *     return sync.tryAcquireNanos(1, unit.toNanos(timeout)); *   } * } * </pre> * * <p>Here is a latch class that is like a {@link CountDownLatch} * except that it only requires a single <tt>signal</tt> to * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt> * acquire and release methods. * * <pre> * class BooleanLatch { * *   private static class Sync extends AbstractQueuedSynchronizer { *     boolean isSignalled() { return getState() != 0; } * *     protected int tryAcquireShared(int ignore) { *       return isSignalled() ? 1 : -1; *     } * *     protected boolean tryReleaseShared(int ignore) { *       setState(1); *       return true; *     } *   } * *   private final Sync sync = new Sync(); *   public boolean isSignalled() { return sync.isSignalled(); } *   public void signal()         { sync.releaseShared(1); } *   public void await() throws InterruptedException { *     sync.acquireSharedInterruptibly(1); *   } * } * </pre> * * @since 1.5 * @author Doug Lea */public abstract class AbstractQueuedSynchronizer    extends AbstractOwnableSynchronizer    implements java.io.Serializable {    private static final long serialVersionUID = 7373984972572414691L;    /**     * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance     * with initial synchronization state of zero.     */    protected AbstractQueuedSynchronizer() { }    /**     * Wait queue node class.     *     * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and     * Hagersten) lock queue. CLH locks are normally used for     * spinlocks.  We instead use them for blocking synchronizers, but     * use the same basic tactic of holding some of the control     * information about a thread in the predecessor of its node.  A     * "status" field in each node keeps track of whether a thread     * should block.  A node is signalled when its predecessor     * releases.  Each node of the queue otherwise serves as a     * specific-notification-style monitor holding a single waiting     * thread. The status field does NOT control whether threads are     * granted locks etc though.  A thread may try to acquire if it is     * first in the queue. But being first does not guarantee success;     * it only gives the right to contend.  So the currently released     * contender thread may need to rewait.     *     * <p>To enqueue into a CLH lock, you atomically splice it in as new     * tail. To dequeue, you just set the head field.     * <pre>     *      +------+  prev +-----+       +-----+     * head |      | <---- |     | <---- |     |  tail     *      +------+       +-----+       +-----+     * </pre>     *     * <p>Insertion into a CLH queue requires only a single atomic     * operation on "tail", so there is a simple atomic point of     * demarcation from unqueued to queued. Similarly, dequeing     * involves only updating the "head". However, it takes a bit     * more work for nodes to determine who their successors are,     * in part to deal with possible cancellation due to timeouts     * and interrupts.     *     * <p>The "prev" links (not used in original CLH locks), are mainly     * needed to handle cancellation. If a node is cancelled, its     * successor is (normally) relinked to a non-cancelled     * predecessor. For explanation of similar mechanics in the case     * of spin locks, see the papers by Scott and Scherer at     * http://www.cs.rochester.edu/u/scott/synchronization/     *     * <p>We also use "next" links to implement blocking mechanics.     * The thread id for each node is kept in its own node, so a     * predecessor signals the next node to wake up by traversing     * next link to determine which thread it is.  Determination of     * successor must avoid races with newly queued nodes to set     * the "next" fields of their predecessors.  This is solved     * when necessary by checking backwards from the atomically     * updated "tail" when a node's successor appears to be null.     * (Or, said differently, the next-links are an optimization     * so that we don't usually need a backward scan.)     *     * <p>Cancellation introduces some conservatism to the basic     * algorithms.  Since we must poll for cancellation of other     * nodes, we can miss noticing whether a cancelled node is     * ahead or behind us. This is dealt with by always unparking     * successors upon cancellation, allowing them to stabilize on     * a new predecessor, unless we can identify an uncancelled     * predecessor who will carry this responsibility.     *     * <p>CLH queues need a dummy header node to get started. But     * we don't create them on construction, because it would be wasted     * effort if there is never contention. Instead, the node     * is constructed and head and tail pointers are set upon first     * contention.     *     * <p>Threads waiting on Conditions use the same nodes, but     * use an additional link. Conditions only need to link nodes     * in simple (non-concurrent) linked queues because they are     * only accessed when exclusively held.  Upon await, a node is     * inserted into a condition queue.  Upon signal, the node is     * transferred to the main queue.  A special value of status     * field is used to mark which queue a node is on.     *     * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill     * Scherer and Michael Scott, along with members of JSR-166     * expert group, for helpful ideas, discussions, and critiques     * on the design of this class.     */    static final class Node {        /** Marker to indicate a node is waiting in shared mode */        static final Node SHARED = new Node();        /** Marker to indicate a node is waiting in exclusive mode */        static final Node EXCLUSIVE = null;        /** waitStatus value to indicate thread has cancelled */        static final int CANCELLED =  1;        /** waitStatus value to indicate successor's thread needs unparking */        static final int SIGNAL    = -1;        /** waitStatus value to indicate thread is waiting on condition */        static final int CONDITION = -2;        /**         * waitStatus value to indicate the next acquireShared should         * unconditionally propagate         */        static final int PROPAGATE = -3;        /**         * Status field, taking on only the values:         *   SIGNAL:     The successor of this node is (or will soon be)         *               blocked (via park), so the current node must         *               unpark its successor when it releases or         *               cancels. To avoid races, acquire methods must         *               first indicate they need a signal,         *               then retry the atomic acquire, and then,         *               on failure, block.         *   CANCELLED:  This node is cancelled due to timeout or interrupt.         *               Nodes never leave this state. In particular,         *               a thread with cancelled node never again blocks.         *   CONDITION:  This node is currently on a condition queue.         *               It will not be used as a sync queue node         *               until transferred, at which time the status         *               will be set to 0. (Use of this value here has         *               nothing to do with the other uses of the         *               field, but simplifies mechanics.)         *   PROPAGATE:  A releaseShared should be propagated to other         *               nodes. This is set (for head node only) in         *               doReleaseShared to ensure propagation         *               continues, even if other operations have         *               since intervened.         *   0:          None of the above         *         * The values are arranged numerically to simplify use.         * Non-negative values mean that a node doesn't need to         * signal. So, most code doesn't need to check for particular         * values, just for sign.         *         * The field is initialized to 0 for normal sync nodes, and         * CONDITION for condition nodes.  It is modified using CAS         * (or when possible, unconditional volatile writes).         */        volatile int waitStatus;        /**         * Link to predecessor node that current node/thread relies on         * for checking waitStatus. Assigned during enqueing, and nulled         * out (for sake of GC) only upon dequeuing.  Also, upon         * cancellation of a predecessor, we short-circuit while         * finding a non-cancelled one, which will always exist         * because the head node is never cancelled: A node becomes         * head only as a result of successful acquire. A         * cancelled thread never succeeds in acquiring, and a thread only         * cancels itself, not any other node.         */        volatile Node prev;        /**         * Link to the successor node that the current node/thread         * unparks upon release. Assigned during enqueuing, adjusted         * when bypassing cancelled predecessors, and nulled out (for         * sake of GC) when dequeued.  The enq operation does not         * assign next field of a predecessor until after attachment,         * so seeing a null next field does not necessarily mean that         * node is at end of queue. However, if a next field appears         * to be null, we can scan prev's from the tail to         * double-check.  The next field of cancelled nodes is set to         * point to the node itself instead of null, to make life         * easier for isOnSyncQueue.         */        volatile Node next;        /**         * The thread that enqueued this node.  Initialized on         * construction and nulled out after use.         */        volatile Thread thread;        /**         * Link to next node waiting on condition, or the special         * value SHARED.  Because condition queues are accessed only         * when holding in exclusive mode, we just need a simple         * linked queue to hold nodes while they are waiting on         * conditions. They are then transferred to the queue to         * re-acquire. And because conditions can only be exclusive,         * we save a field by using special value to indicate shared         * mode.         */        Node nextWaiter;        /**         * Returns true if node is waiting in shared mode         */        final boolean isShared() {            return nextWaiter == SHARED;        }        /**         * Returns previous node, or throws NullPointerException if null.         * Use when predecessor cannot be null.  The null check could         * be elided, but is present to help the VM.         *         * @return the predecessor of this node         */        final Node predecessor() throws NullPointerException {            Node p = prev;            if (p == null)                throw new NullPointerException();            else                return p;        }        Node() {    // Used to establish initial head or SHARED marker        }        Node(Thread thread, Node mode) {     // Used by addWaiter            this.nextWaiter = mode;            this.thread = thread;        }        Node(Thread thread, int waitStatus) { // Used by Condition            this.waitStatus = waitStatus;            this.thread = thread;        }    }    /**     * Head of the wait queue, lazily initialized.  Except for     * initialization, it is modified only via method setHead.  Note:     * If head exists, its waitStatus is guaranteed not to be     * CANCELLED.     */    private transient volatile Node head;    /**     * Tail of the wait queue, lazily initialized.  Modified only via     * method enq to add new wait node.     */    private transient volatile Node tail;    /**     * The synchronization state.     */    private volatile int state;    /**     * Returns the current value of synchronization state.     * This operation has memory semantics of a <tt>volatile</tt> read.     * @return current state value     */    protected final int getState() {        return state;    }    /**     * Sets the value of synchronization state.     * This operation has memory semantics of a <tt>volatile</tt> write.     * @param newState the new state value     */    protected final void setState(int newState) {        state = newState;    }    /**     * Atomically sets synchronization state to the given updated     * value if the current state value equals the expected value.     * This operation has memory semantics of a <tt>volatile</tt> read     * and write.     *     * @param expect the expected value     * @param update the new value     * @return true if successful. False return indicates that the actual     *         value was not equal to the expected value.     */    protected final boolean compareAndSetState(int expect, int update) {        // See below for intrinsics setup to support this        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);    }    // Queuing utilities    /**     * The number of nanoseconds for which it is faster to spin     * rather than to use timed park. A rough estimate suffices     * to improve responsiveness with very short timeouts.     */    static final long spinForTimeoutThreshold = 1000L;    /**     * Inserts node into queue, initializing if necessary. See picture above.     * @param node the node to insert     * @return node's predecessor     */    private Node enq(final Node node) {        for (;;) {            Node t = tail;            if (t == null) { // Must initialize                if (compareAndSetHead(new Node()))                    tail = head;            } else {                node.prev = t;                if (compareAndSetTail(t, node)) {                    t.next = node;                    return t;                }            }        }    }    /**     * Creates and enqueues node for current thread and given mode.     *     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared     * @return the new node     */    private Node addWaiter(Node mode) {        Node node = new Node(Thread.currentThread(), mode);        // Try the fast path of enq; backup to full enq on failure        Node pred = tail;        if (pred != null) {            node.prev = pred;            if (compareAndSetTail(pred, node)) {                pred.next = node;                return node;            }        }        enq(node);        return node;    }    /**     * Sets head of queue to be node, thus dequeuing. Called only by     * acquire methods.  Also nulls out unused fields for sake of GC     * and to suppress unnecessary signals and traversals.     *     * @param node the node     */    private void setHead(Node node) {        head = node;        node.thread = null;        node.prev = null;    }    /**     * Wakes up node's successor, if one exists.     *     * @param node the node     */    private void unparkSuccessor(Node node) {        /*         * If status is negative (i.e., possibly needing signal) try         * to clear in anticipation of signalling.  It is OK if this         * fails or if status is changed by waiting thread.         */        int ws = node.waitStatus;        if (ws < 0)            compareAndSetWaitStatus(node, ws, 0);        /*         * Thread to unpark is held in successor, which is normally         * just the next node.  But if cancelled or apparently null,         * traverse backwards from tail to find the actual         * non-cancelled successor.         */        Node s = node.next;        if (s == null || s.waitStatus > 0) {            s = null;            for (Node t = tail; t != null && t != node; t = t.prev)                if (t.waitStatus <= 0)                    s = t;        }        if (s != null)            LockSupport.unpark(s.thread);    }    /**     * Release action for shared mode -- signal successor and ensure     * propagation. (Note: For exclusive mode, release just amounts     * to calling unparkSuccessor of head if it needs signal.)     */    private void doReleaseShared() {        /*         * Ensure that a release propagates, even if there are other         * in-progress acquires/releases.  This proceeds in the usual         * way of trying to unparkSuccessor of head if it needs         * signal. But if it does not, status is set to PROPAGATE to         * ensure that upon release, propagation continues.         * Additionally, we must loop in case a new node is added         * while we are doing this. Also, unlike other uses of         * unparkSuccessor, we need to know if CAS to reset status         * fails, if so rechecking.         */        for (;;) {            Node h = head;            if (h != null && h != tail) {                int ws = h.waitStatus;                if (ws == Node.SIGNAL) {                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))                        continue;            // loop to recheck cases                    unparkSuccessor(h);                }                else if (ws == 0 &&                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))                    continue;                // loop on failed CAS            }            if (h == head)                   // loop if head changed                break;        }    }    /**     * Sets head of queue, and checks if successor may be waiting     * in shared mode, if so propagating if either propagate > 0 or     * PROPAGATE status was set.     *     * @param node the node     * @param propagate the return value from a tryAcquireShared     */    private void setHeadAndPropagate(Node node, int propagate) {        Node h = head; // Record old head for check below        setHead(node);        /*         * Try to signal next queued node if:         *   Propagation was indicated by caller,         *     or was recorded (as h.waitStatus) by a previous operation         *     (note: this uses sign-check of waitStatus because         *      PROPAGATE status may transition to SIGNAL.)         * and         *   The next node is waiting in shared mode,         *     or we don't know, because it appears null         *         * The conservatism in both of these checks may cause         * unnecessary wake-ups, but only when there are multiple         * racing acquires/releases, so most need signals now or soon         * anyway.         */        if (propagate > 0 || h == null || h.waitStatus < 0) {            Node s = node.next;            if (s == null || s.isShared())                doReleaseShared();        }    }    // Utilities for various versions of acquire    /**     * Cancels an ongoing attempt to acquire.     *     * @param node the node     */    private void cancelAcquire(Node node) {        // Ignore if node doesn't exist        if (node == null)            return;        node.thread = null;        // Skip cancelled predecessors        Node pred = node.prev;        while (pred.waitStatus > 0)            node.prev = pred = pred.prev;        // predNext is the apparent node to unsplice. CASes below will        // fail if not, in which case, we lost race vs another cancel        // or signal, so no further action is necessary.        Node predNext = pred.next;        // Can use unconditional write instead of CAS here.        // After this atomic step, other Nodes can skip past us.        // Before, we are free of interference from other threads.        node.waitStatus = Node.CANCELLED;        // If we are the tail, remove ourselves.        if (node == tail && compareAndSetTail(node, pred)) {            compareAndSetNext(pred, predNext, null);        } else {            // If successor needs signal, try to set pred's next-link            // so it will get one. Otherwise wake it up to propagate.            int ws;            if (pred != head &&                ((ws = pred.waitStatus) == Node.SIGNAL ||                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&                pred.thread != null) {                Node next = node.next;                if (next != null && next.waitStatus <= 0)                    compareAndSetNext(pred, predNext, next);            } else {                unparkSuccessor(node);            }            node.next = node; // help GC        }    }    /**     * Checks and updates status for a node that failed to acquire.     * Returns true if thread should block. This is the main signal     * control in all acquire loops.  Requires that pred == node.prev     *     * @param pred node's predecessor holding status     * @param node the node     * @return {@code true} if thread should block     */    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {        int ws = pred.waitStatus;        if (ws == Node.SIGNAL)            /*             * This node has already set status asking a release             * to signal it, so it can safely park.             */            return true;        if (ws > 0) {            /*             * Predecessor was cancelled. Skip over predecessors and             * indicate retry.             */            do {                node.prev = pred = pred.prev;            } while (pred.waitStatus > 0);            pred.next = node;        } else {            /*             * waitStatus must be 0 or PROPAGATE.  Indicate that we             * need a signal, but don't park yet.  Caller will need to             * retry to make sure it cannot acquire before parking.             */            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);        }        return false;    }    /**     * Convenience method to interrupt current thread.     */    private static void selfInterrupt() {        Thread.currentThread().interrupt();    }    /**     * Convenience method to park and then check if interrupted     *     * @return {@code true} if interrupted     */    private final boolean parkAndCheckInterrupt() {        LockSupport.park(this);        return Thread.interrupted();    }    /*     * Various flavors of acquire, varying in exclusive/shared and     * control modes.  Each is mostly the same, but annoyingly     * different.  Only a little bit of factoring is possible due to     * interactions of exception mechanics (including ensuring that we     * cancel if tryAcquire throws exception) and other control, at     * least not without hurting performance too much.     */    /**     * Acquires in exclusive uninterruptible mode for thread already in     * queue. Used by condition wait methods as well as acquire.     *     * @param node the node     * @param arg the acquire argument     * @return {@code true} if interrupted while waiting     */    final boolean acquireQueued(final Node node, int arg) {        boolean failed = true;        try {            boolean interrupted = false;            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    failed = false;                    return interrupted;                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    interrupted = true;            }        } finally {            if (failed)                cancelAcquire(node);        }    }    /**     * Acquires in exclusive interruptible mode.     * @param arg the acquire argument     */    private void doAcquireInterruptibly(int arg)        throws InterruptedException {        final Node node = addWaiter(Node.EXCLUSIVE);        boolean failed = true;        try {            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    failed = false;                    return;                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    throw new InterruptedException();            }        } finally {            if (failed)                cancelAcquire(node);        }    }    /**     * Acquires in exclusive timed mode.     *     * @param arg the acquire argument     * @param nanosTimeout max wait time     * @return {@code true} if acquired     */    private boolean doAcquireNanos(int arg, long nanosTimeout)        throws InterruptedException {        long lastTime = System.nanoTime();        final Node node = addWaiter(Node.EXCLUSIVE);        boolean failed = true;        try {            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    failed = false;                    return true;                }                if (nanosTimeout <= 0)                    return false;                if (shouldParkAfterFailedAcquire(p, node) &&                    nanosTimeout > spinForTimeoutThreshold)                    LockSupport.parkNanos(this, nanosTimeout);                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;                if (Thread.interrupted())                    throw new InterruptedException();            }        } finally {            if (failed)                cancelAcquire(node);        }    }    /**     * Acquires in shared uninterruptible mode.     * @param arg the acquire argument     */    private void doAcquireShared(int arg) {        final Node node = addWaiter(Node.SHARED);        boolean failed = true;        try {            boolean interrupted = false;            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    int r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        if (interrupted)                            selfInterrupt();                        failed = false;                        return;                    }                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    interrupted = true;            }        } finally {            if (failed)                cancelAcquire(node);        }    }    /**     * Acquires in shared interruptible mode.     * @param arg the acquire argument     */    private void doAcquireSharedInterruptibly(int arg)        throws InterruptedException {        final Node node = addWaiter(Node.SHARED);        boolean failed = true;        try {            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    int r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        failed = false;                        return;                    }                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    throw new InterruptedException();            }        } finally {            if (failed)                cancelAcquire(node);        }    }    /**     * Acquires in shared timed mode.     *     * @param arg the acquire argument     * @param nanosTimeout max wait time     * @return {@code true} if acquired     */    private boolean doAcquireSharedNanos(int arg, long nanosTimeout)        throws InterruptedException {        long lastTime = System.nanoTime();        final Node node = addWaiter(Node.SHARED);        boolean failed = true;        try {            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    int r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        failed = false;                        return true;                    }                }                if (nanosTimeout <= 0)                    return false;                if (shouldParkAfterFailedAcquire(p, node) &&                    nanosTimeout > spinForTimeoutThreshold)                    LockSupport.parkNanos(this, nanosTimeout);                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;                if (Thread.interrupted())                    throw new InterruptedException();            }        } finally {            if (failed)                cancelAcquire(node);        }    }    // Main exported methods    /**     * Attempts to acquire in exclusive mode. This method should query     * if the state of the object permits it to be acquired in the     * exclusive mode, and if so to acquire it.     *     * <p>This method is always invoked by the thread performing     * acquire.  If this method reports failure, the acquire method     * may queue the thread, if it is not already queued, until it is     * signalled by a release from some other thread. This can be used     * to implement method {@link Lock#tryLock()}.     *     * <p>The default     * implementation throws {@link UnsupportedOperationException}.     *     * @param arg the acquire argument. This value is always the one     *        passed to an acquire method, or is the value saved on entry     *        to a condition wait.  The value is otherwise uninterpreted     *        and can represent anything you like.     * @return {@code true} if successful. Upon success, this object has     *         been acquired.     * @throws IllegalMonitorStateException if acquiring would place this     *         synchronizer in an illegal state. This exception must be     *         thrown in a consistent fashion for synchronization to work     *         correctly.     * @throws UnsupportedOperationException if exclusive mode is not supported     */    protected boolean tryAcquire(int arg) {        throw new UnsupportedOperationException();    }    /**     * Attempts to set the state to reflect a release in exclusive     * mode.     *     * <p>This method is always invoked by the thread performing release.     *     * <p>The default implementation throws     * {@link UnsupportedOperationException}.     *     * @param arg the release argument. This value is always the one     *        passed to a release method, or the current state value upon     *        entry to a condition wait.  The value is otherwise     *        uninterpreted and can represent anything you like.     * @return {@code true} if this object is now in a fully released     *         state, so that any waiting threads may attempt to acquire;     *         and {@code false} otherwise.     * @throws IllegalMonitorStateException if releasing would place this     *         synchronizer in an illegal state. This exception must be     *         thrown in a consistent fashion for synchronization to work     *         correctly.     * @throws UnsupportedOperationException if exclusive mode is not supported     */    protected boolean tryRelease(int arg) {        throw new UnsupportedOperationException();    }    /**     * Attempts to acquire in shared mode. This method should query if     * the state of the object permits it to be acquired in the shared     * mode, and if so to acquire it.     *     * <p>This method is always invoked by the thread performing     * acquire.  If this method reports failure, the acquire method     * may queue the thread, if it is not already queued, until it is     * signalled by a release from some other thread.     *     * <p>The default implementation throws {@link     * UnsupportedOperationException}.     *     * @param arg the acquire argument. This value is always the one     *        passed to an acquire method, or is the value saved on entry     *        to a condition wait.  The value is otherwise uninterpreted     *        and can represent anything you like.     * @return a negative value on failure; zero if acquisition in shared     *         mode succeeded but no subsequent shared-mode acquire can     *         succeed; and a positive value if acquisition in shared     *         mode succeeded and subsequent shared-mode acquires might     *         also succeed, in which case a subsequent waiting thread     *         must check availability. (Support for three different     *         return values enables this method to be used in contexts     *         where acquires only sometimes act exclusively.)  Upon     *         success, this object has been acquired.     * @throws IllegalMonitorStateException if acquiring would place this     *         synchronizer in an illegal state. This exception must be     *         thrown in a consistent fashion for synchronization to work     *         correctly.     * @throws UnsupportedOperationException if shared mode is not supported     */    protected int tryAcquireShared(int arg) {        throw new UnsupportedOperationException();    }    /**     * Attempts to set the state to reflect a release in shared mode.     *     * <p>This method is always invoked by the thread performing release.     *     * <p>The default implementation throws     * {@link UnsupportedOperationException}.     *     * @param arg the release argument. This value is always the one     *        passed to a release method, or the current state value upon     *        entry to a condition wait.  The value is otherwise     *        uninterpreted and can represent anything you like.     * @return {@code true} if this release of shared mode may permit a     *         waiting acquire (shared or exclusive) to succeed; and     *         {@code false} otherwise     * @throws IllegalMonitorStateException if releasing would place this     *         synchronizer in an illegal state. This exception must be     *         thrown in a consistent fashion for synchronization to work     *         correctly.     * @throws UnsupportedOperationException if shared mode is not supported     */    protected boolean tryReleaseShared(int arg) {        throw new UnsupportedOperationException();    }    /**     * Returns {@code true} if synchronization is held exclusively with     * respect to the current (calling) thread.  This method is invoked     * upon each call to a non-waiting {@link ConditionObject} method.     * (Waiting methods instead invoke {@link #release}.)     *     * <p>The default implementation throws {@link     * UnsupportedOperationException}. This method is invoked     * internally only within {@link ConditionObject} methods, so need     * not be defined if conditions are not used.     *     * @return {@code true} if synchronization is held exclusively;     *         {@code false} otherwise     * @throws UnsupportedOperationException if conditions are not supported     */    protected boolean isHeldExclusively() {        throw new UnsupportedOperationException();    }    /**     * Acquires in exclusive mode, ignoring interrupts.  Implemented     * by invoking at least once {@link #tryAcquire},     * returning on success.  Otherwise the thread is queued, possibly     * repeatedly blocking and unblocking, invoking {@link     * #tryAcquire} until success.  This method can be used     * to implement method {@link Lock#lock}.     *     * @param arg the acquire argument.  This value is conveyed to     *        {@link #tryAcquire} but is otherwise uninterpreted and     *        can represent anything you like.     */    public final void acquire(int arg) {        if (!tryAcquire(arg) &&            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))            selfInterrupt();    }    /**     * Acquires in exclusive mode, aborting if interrupted.     * Implemented by first checking interrupt status, then invoking     * at least once {@link #tryAcquire}, returning on     * success.  Otherwise the thread is queued, possibly repeatedly     * blocking and unblocking, invoking {@link #tryAcquire}     * until success or the thread is interrupted.  This method can be     * used to implement method {@link Lock#lockInterruptibly}.     *     * @param arg the acquire argument.  This value is conveyed to     *        {@link #tryAcquire} but is otherwise uninterpreted and     *        can represent anything you like.     * @throws InterruptedException if the current thread is interrupted     */    public final void acquireInterruptibly(int arg)            throws InterruptedException {        if (Thread.interrupted())            throw new InterruptedException();        if (!tryAcquire(arg))            doAcquireInterruptibly(arg);    }    /**     * Attempts to acquire in exclusive mode, aborting if interrupted,     * and failing if the given timeout elapses.  Implemented by first     * checking interrupt status, then invoking at least once {@link     * #tryAcquire}, returning on success.  Otherwise, the thread is     * queued, possibly repeatedly blocking and unblocking, invoking     * {@link #tryAcquire} until success or the thread is interrupted     * or the timeout elapses.  This method can be used to implement     * method {@link Lock#tryLock(long, TimeUnit)}.     *     * @param arg the acquire argument.  This value is conveyed to     *        {@link #tryAcquire} but is otherwise uninterpreted and     *        can represent anything you like.     * @param nanosTimeout the maximum number of nanoseconds to wait     * @return {@code true} if acquired; {@code false} if timed out     * @throws InterruptedException if the current thread is interrupted     */    public final boolean tryAcquireNanos(int arg, long nanosTimeout)            throws InterruptedException {        if (Thread.interrupted())            throw new InterruptedException();        return tryAcquire(arg) ||            doAcquireNanos(arg, nanosTimeout);    }    /**     * Releases in exclusive mode.  Implemented by unblocking one or     * more threads if {@link #tryRelease} returns true.     * This method can be used to implement method {@link Lock#unlock}.     *     * @param arg the release argument.  This value is conveyed to     *        {@link #tryRelease} but is otherwise uninterpreted and     *        can represent anything you like.     * @return the value returned from {@link #tryRelease}     */    public final boolean release(int arg) {        if (tryRelease(arg)) {            Node h = head;            if (h != null && h.waitStatus != 0)                unparkSuccessor(h);            return true;        }        return false;    }    /**     * Acquires in shared mode, ignoring interrupts.  Implemented by     * first invoking at least once {@link #tryAcquireShared},     * returning on success.  Otherwise the thread is queued, possibly     * repeatedly blocking and unblocking, invoking {@link     * #tryAcquireShared} until success.     *     * @param arg the acquire argument.  This value is conveyed to     *        {@link #tryAcquireShared} but is otherwise uninterpreted     *        and can represent anything you like.     */    public final void acquireShared(int arg) {        if (tryAcquireShared(arg) < 0)            doAcquireShared(arg);    }    /**     * Acquires in shared mode, aborting if interrupted.  Implemented     * by first checking interrupt status, then invoking at least once     * {@link #tryAcquireShared}, returning on success.  Otherwise the     * thread is queued, possibly repeatedly blocking and unblocking,     * invoking {@link #tryAcquireShared} until success or the thread     * is interrupted.     * @param arg the acquire argument     * This value is conveyed to {@link #tryAcquireShared} but is     * otherwise uninterpreted and can represent anything     * you like.     * @throws InterruptedException if the current thread is interrupted     */    public final void acquireSharedInterruptibly(int arg)            throws InterruptedException {        if (Thread.interrupted())            throw new InterruptedException();        if (tryAcquireShared(arg) < 0)            doAcquireSharedInterruptibly(arg);    }    /**     * Attempts to acquire in shared mode, aborting if interrupted, and     * failing if the given timeout elapses.  Implemented by first     * checking interrupt status, then invoking at least once {@link     * #tryAcquireShared}, returning on success.  Otherwise, the     * thread is queued, possibly repeatedly blocking and unblocking,     * invoking {@link #tryAcquireShared} until success or the thread     * is interrupted or the timeout elapses.     *     * @param arg the acquire argument.  This value is conveyed to     *        {@link #tryAcquireShared} but is otherwise uninterpreted     *        and can represent anything you like.     * @param nanosTimeout the maximum number of nanoseconds to wait     * @return {@code true} if acquired; {@code false} if timed out     * @throws InterruptedException if the current thread is interrupted     */    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)            throws InterruptedException {        if (Thread.interrupted())            throw new InterruptedException();        return tryAcquireShared(arg) >= 0 ||            doAcquireSharedNanos(arg, nanosTimeout);    }    /**     * Releases in shared mode.  Implemented by unblocking one or more     * threads if {@link #tryReleaseShared} returns true.     *     * @param arg the release argument.  This value is conveyed to     *        {@link #tryReleaseShared} but is otherwise uninterpreted     *        and can represent anything you like.     * @return the value returned from {@link #tryReleaseShared}     */    public final boolean releaseShared(int arg) {        if (tryReleaseShared(arg)) {            doReleaseShared();            return true;        }        return false;    }    // Queue inspection methods    /**     * Queries whether any threads are waiting to acquire. Note that     * because cancellations due to interrupts and timeouts may occur     * at any time, a {@code true} return does not guarantee that any     * other thread will ever acquire.     *     * <p>In this implementation, this operation returns in     * constant time.     *     * @return {@code true} if there may be other threads waiting to acquire     */    public final boolean hasQueuedThreads() {        return head != tail;    }    /**     * Queries whether any threads have ever contended to acquire this     * synchronizer; that is if an acquire method has ever blocked.     *     * <p>In this implementation, this operation returns in     * constant time.     *     * @return {@code true} if there has ever been contention     */    public final boolean hasContended() {        return head != null;    }    /**     * Returns the first (longest-waiting) thread in the queue, or     * {@code null} if no threads are currently queued.     *     * <p>In this implementation, this operation normally returns in     * constant time, but may iterate upon contention if other threads are     * concurrently modifying the queue.     *     * @return the first (longest-waiting) thread in the queue, or     *         {@code null} if no threads are currently queued     */    public final Thread getFirstQueuedThread() {        // handle only fast path, else relay        return (head == tail) ? null : fullGetFirstQueuedThread();    }    /**     * Version of getFirstQueuedThread called when fastpath fails     */    private Thread fullGetFirstQueuedThread() {        /*         * The first node is normally head.next. Try to get its         * thread field, ensuring consistent reads: If thread         * field is nulled out or s.prev is no longer head, then         * some other thread(s) concurrently performed setHead in         * between some of our reads. We try this twice before         * resorting to traversal.         */        Node h, s;        Thread st;        if (((h = head) != null && (s = h.next) != null &&             s.prev == head && (st = s.thread) != null) ||            ((h = head) != null && (s = h.next) != null &&             s.prev == head && (st = s.thread) != null))            return st;        /*         * Head's next field might not have been set yet, or may have         * been unset after setHead. So we must check to see if tail         * is actually first node. If not, we continue on, safely         * traversing from tail back to head to find first,         * guaranteeing termination.         */        Node t = tail;        Thread firstThread = null;        while (t != null && t != head) {            Thread tt = t.thread;            if (tt != null)                firstThread = tt;            t = t.prev;        }        return firstThread;    }    /**     * Returns true if the given thread is currently queued.     *     * <p>This implementation traverses the queue to determine     * presence of the given thread.     *     * @param thread the thread     * @return {@code true} if the given thread is on the queue     * @throws NullPointerException if the thread is null     */    public final boolean isQueued(Thread thread) {        if (thread == null)            throw new NullPointerException();        for (Node p = tail; p != null; p = p.prev)            if (p.thread == thread)                return true;        return false;    }    /**     * Returns {@code true} if the apparent first queued thread, if one     * exists, is waiting in exclusive mode.  If this method returns     * {@code true}, and the current thread is attempting to acquire in     * shared mode (that is, this method is invoked from {@link     * #tryAcquireShared}) then it is guaranteed that the current thread     * is not the first queued thread.  Used only as a heuristic in     * ReentrantReadWriteLock.     */    final boolean apparentlyFirstQueuedIsExclusive() {        Node h, s;        return (h = head) != null &&            (s = h.next)  != null &&            !s.isShared()         &&            s.thread != null;    }    /**     * Queries whether any threads have been waiting to acquire longer     * than the current thread.     *     * <p>An invocation of this method is equivalent to (but may be     * more efficient than):     *  <pre> {@code     * getFirstQueuedThread() != Thread.currentThread() &&     * hasQueuedThreads()}</pre>     *     * <p>Note that because cancellations due to interrupts and     * timeouts may occur at any time, a {@code true} return does not     * guarantee that some other thread will acquire before the current     * thread.  Likewise, it is possible for another thread to win a     * race to enqueue after this method has returned {@code false},     * due to the queue being empty.     *     * <p>This method is designed to be used by a fair synchronizer to     * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.     * Such a synchronizer's {@link #tryAcquire} method should return     * {@code false}, and its {@link #tryAcquireShared} method should     * return a negative value, if this method returns {@code true}     * (unless this is a reentrant acquire).  For example, the {@code     * tryAcquire} method for a fair, reentrant, exclusive mode     * synchronizer might look like this:     *     *  <pre> {@code     * protected boolean tryAcquire(int arg) {     *   if (isHeldExclusively()) {     *     // A reentrant acquire; increment hold count     *     return true;     *   } else if (hasQueuedPredecessors()) {     *     return false;     *   } else {     *     // try to acquire normally     *   }     * }}</pre>     *     * @return {@code true} if there is a queued thread preceding the     *         current thread, and {@code false} if the current thread     *         is at the head of the queue or the queue is empty     * @since 1.7     */    public final boolean hasQueuedPredecessors() {        // The correctness of this depends on head being initialized        // before tail and on head.next being accurate if the current        // thread is first in queue.        Node t = tail; // Read fields in reverse initialization order        Node h = head;        Node s;        return h != t &&            ((s = h.next) == null || s.thread != Thread.currentThread());    }    // Instrumentation and monitoring methods    /**     * Returns an estimate of the number of threads waiting to     * acquire.  The value is only an estimate because the number of     * threads may change dynamically while this method traverses     * internal data structures.  This method is designed for use in     * monitoring system state, not for synchronization     * control.     *     * @return the estimated number of threads waiting to acquire     */    public final int getQueueLength() {        int n = 0;        for (Node p = tail; p != null; p = p.prev) {            if (p.thread != null)                ++n;        }        return n;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire.  Because the actual set of threads may change     * dynamically while constructing this result, the returned     * collection is only a best-effort estimate.  The elements of the     * returned collection are in no particular order.  This method is     * designed to facilitate construction of subclasses that provide     * more extensive monitoring facilities.     *     * @return the collection of threads     */    public final Collection<Thread> getQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            Thread t = p.thread;            if (t != null)                list.add(t);        }        return list;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire in exclusive mode. This has the same properties     * as {@link #getQueuedThreads} except that it only returns     * those threads waiting due to an exclusive acquire.     *     * @return the collection of threads     */    public final Collection<Thread> getExclusiveQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            if (!p.isShared()) {                Thread t = p.thread;                if (t != null)                    list.add(t);            }        }        return list;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire in shared mode. This has the same properties     * as {@link #getQueuedThreads} except that it only returns     * those threads waiting due to a shared acquire.     *     * @return the collection of threads     */    public final Collection<Thread> getSharedQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            if (p.isShared()) {                Thread t = p.thread;                if (t != null)                    list.add(t);            }        }        return list;    }    /**     * Returns a string identifying this synchronizer, as well as its state.     * The state, in brackets, includes the String {@code "State ="}     * followed by the current value of {@link #getState}, and either     * {@code "nonempty"} or {@code "empty"} depending on whether the     * queue is empty.     *     * @return a string identifying this synchronizer, as well as its state     */    public String toString() {        int s = getState();        String q  = hasQueuedThreads() ? "non" : "";        return super.toString() +            "[State = " + s + ", " + q + "empty queue]";    }    // Internal support methods for Conditions    /**     * Returns true if a node, always one that was initially placed on     * a condition queue, is now waiting to reacquire on sync queue.     * @param node the node     * @return true if is reacquiring     */    final boolean isOnSyncQueue(Node node) {        if (node.waitStatus == Node.CONDITION || node.prev == null)            return false;        if (node.next != null) // If has successor, it must be on queue            return true;        /*         * node.prev can be non-null, but not yet on queue because         * the CAS to place it on queue can fail. So we have to         * traverse from tail to make sure it actually made it.  It         * will always be near the tail in calls to this method, and         * unless the CAS failed (which is unlikely), it will be         * there, so we hardly ever traverse much.         */        return findNodeFromTail(node);    }    /**     * Returns true if node is on sync queue by searching backwards from tail.     * Called only when needed by isOnSyncQueue.     * @return true if present     */    private boolean findNodeFromTail(Node node) {        Node t = tail;        for (;;) {            if (t == node)                return true;            if (t == null)                return false;            t = t.prev;        }    }    /**     * Transfers a node from a condition queue onto sync queue.     * Returns true if successful.     * @param node the node     * @return true if successfully transferred (else the node was     * cancelled before signal).     */    final boolean transferForSignal(Node node) {        /*         * If cannot change waitStatus, the node has been cancelled.         */        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))            return false;        /*         * Splice onto queue and try to set waitStatus of predecessor to         * indicate that thread is (probably) waiting. If cancelled or         * attempt to set waitStatus fails, wake up to resync (in which         * case the waitStatus can be transiently and harmlessly wrong).         */        Node p = enq(node);        int ws = p.waitStatus;        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))            LockSupport.unpark(node.thread);        return true;    }    /**     * Transfers node, if necessary, to sync queue after a cancelled     * wait. Returns true if thread was cancelled before being     * signalled.     * @param current the waiting thread     * @param node its node     * @return true if cancelled before the node was signalled     */    final boolean transferAfterCancelledWait(Node node) {        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {            enq(node);            return true;        }        /*         * If we lost out to a signal(), then we can't proceed         * until it finishes its enq().  Cancelling during an         * incomplete transfer is both rare and transient, so just         * spin.         */        while (!isOnSyncQueue(node))            Thread.yield();        return false;    }    /**     * Invokes release with current state value; returns saved state.     * Cancels node and throws exception on failure.     * @param node the condition node for this wait     * @return previous sync state     */    final int fullyRelease(Node node) {        boolean failed = true;        try {            int savedState = getState();            if (release(savedState)) {                failed = false;                return savedState;            } else {                throw new IllegalMonitorStateException();            }        } finally {            if (failed)                node.waitStatus = Node.CANCELLED;        }    }    // Instrumentation methods for conditions    /**     * Queries whether the given ConditionObject     * uses this synchronizer as its lock.     *     * @param condition the condition     * @return <tt>true</tt> if owned     * @throws NullPointerException if the condition is null     */    public final boolean owns(ConditionObject condition) {        if (condition == null)            throw new NullPointerException();        return condition.isOwnedBy(this);    }    /**     * Queries whether any threads are waiting on the given condition     * associated with this synchronizer. Note that because timeouts     * and interrupts may occur at any time, a <tt>true</tt> return     * does not guarantee that a future <tt>signal</tt> will awaken     * any threads.  This method is designed primarily for use in     * monitoring of the system state.     *     * @param condition the condition     * @return <tt>true</tt> if there are any waiting threads     * @throws IllegalMonitorStateException if exclusive synchronization     *         is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this synchronizer     * @throws NullPointerException if the condition is null     */    public final boolean hasWaiters(ConditionObject condition) {        if (!owns(condition))            throw new IllegalArgumentException("Not owner");        return condition.hasWaiters();    }    /**     * Returns an estimate of the number of threads waiting on the     * given condition associated with this synchronizer. Note that     * because timeouts and interrupts may occur at any time, the     * estimate serves only as an upper bound on the actual number of     * waiters.  This method is designed for use in monitoring of the     * system state, not for synchronization control.     *     * @param condition the condition     * @return the estimated number of waiting threads     * @throws IllegalMonitorStateException if exclusive synchronization     *         is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this synchronizer     * @throws NullPointerException if the condition is null     */    public final int getWaitQueueLength(ConditionObject condition) {        if (!owns(condition))            throw new IllegalArgumentException("Not owner");        return condition.getWaitQueueLength();    }    /**     * Returns a collection containing those threads that may be     * waiting on the given condition associated with this     * synchronizer.  Because the actual set of threads may change     * dynamically while constructing this result, the returned     * collection is only a best-effort estimate. The elements of the     * returned collection are in no particular order.     *     * @param condition the condition     * @return the collection of threads     * @throws IllegalMonitorStateException if exclusive synchronization     *         is not held     * @throws IllegalArgumentException if the given condition is     *         not associated with this synchronizer     * @throws NullPointerException if the condition is null     */    public final Collection<Thread> getWaitingThreads(ConditionObject condition) {        if (!owns(condition))            throw new IllegalArgumentException("Not owner");        return condition.getWaitingThreads();    }    /**     * Condition implementation for a {@link     * AbstractQueuedSynchronizer} serving as the basis of a {@link     * Lock} implementation.     *     * <p>Method documentation for this class describes mechanics,     * not behavioral specifications from the point of view of Lock     * and Condition users. Exported versions of this class will in     * general need to be accompanied by documentation describing     * condition semantics that rely on those of the associated     * <tt>AbstractQueuedSynchronizer</tt>.     *     * <p>This class is Serializable, but all fields are transient,     * so deserialized conditions have no waiters.     */    public class ConditionObject implements Condition, java.io.Serializable {        private static final long serialVersionUID = 1173984872572414699L;        /** First node of condition queue. */        private transient Node firstWaiter;        /** Last node of condition queue. */        private transient Node lastWaiter;        /**         * Creates a new <tt>ConditionObject</tt> instance.         */        public ConditionObject() { }        // Internal methods        /**         * Adds a new waiter to wait queue.         * @return its new wait node         */        private Node addConditionWaiter() {            Node t = lastWaiter;            // If lastWaiter is cancelled, clean out.            if (t != null && t.waitStatus != Node.CONDITION) {                unlinkCancelledWaiters();                t = lastWaiter;            }            Node node = new Node(Thread.currentThread(), Node.CONDITION);            if (t == null)                firstWaiter = node;            else                t.nextWaiter = node;            lastWaiter = node;            return node;        }        /**         * Removes and transfers nodes until hit non-cancelled one or         * null. Split out from signal in part to encourage compilers         * to inline the case of no waiters.         * @param first (non-null) the first node on condition queue         */        private void doSignal(Node first) {            do {                if ( (firstWaiter = first.nextWaiter) == null)                    lastWaiter = null;                first.nextWaiter = null;            } while (!transferForSignal(first) &&                     (first = firstWaiter) != null);        }        /**         * Removes and transfers all nodes.         * @param first (non-null) the first node on condition queue         */        private void doSignalAll(Node first) {            lastWaiter = firstWaiter = null;            do {                Node next = first.nextWaiter;                first.nextWaiter = null;                transferForSignal(first);                first = next;            } while (first != null);        }        /**         * Unlinks cancelled waiter nodes from condition queue.         * Called only while holding lock. This is called when         * cancellation occurred during condition wait, and upon         * insertion of a new waiter when lastWaiter is seen to have         * been cancelled. This method is needed to avoid garbage         * retention in the absence of signals. So even though it may         * require a full traversal, it comes into play only when         * timeouts or cancellations occur in the absence of         * signals. It traverses all nodes rather than stopping at a         * particular target to unlink all pointers to garbage nodes         * without requiring many re-traversals during cancellation         * storms.         */        private void unlinkCancelledWaiters() {            Node t = firstWaiter;            Node trail = null;            while (t != null) {                Node next = t.nextWaiter;                if (t.waitStatus != Node.CONDITION) {                    t.nextWaiter = null;                    if (trail == null)                        firstWaiter = next;                    else                        trail.nextWaiter = next;                    if (next == null)                        lastWaiter = trail;                }                else                    trail = t;                t = next;            }        }        // public methods        /**         * Moves the longest-waiting thread, if one exists, from the         * wait queue for this condition to the wait queue for the         * owning lock.         *         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}         *         returns {@code false}         */        public final void signal() {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            Node first = firstWaiter;            if (first != null)                doSignal(first);        }        /**         * Moves all threads from the wait queue for this condition to         * the wait queue for the owning lock.         *         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}         *         returns {@code false}         */        public final void signalAll() {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            Node first = firstWaiter;            if (first != null)                doSignalAll(first);        }        /**         * Implements uninterruptible condition wait.         * <ol>         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * </ol>         */        public final void awaitUninterruptibly() {            Node node = addConditionWaiter();            int savedState = fullyRelease(node);            boolean interrupted = false;            while (!isOnSyncQueue(node)) {                LockSupport.park(this);                if (Thread.interrupted())                    interrupted = true;            }            if (acquireQueued(node, savedState) || interrupted)                selfInterrupt();        }        /*         * For interruptible waits, we need to track whether to throw         * InterruptedException, if interrupted while blocked on         * condition, versus reinterrupt current thread, if         * interrupted while blocked waiting to re-acquire.         */        /** Mode meaning to reinterrupt on exit from wait */        private static final int REINTERRUPT =  1;        /** Mode meaning to throw InterruptedException on exit from wait */        private static final int THROW_IE    = -1;        /**         * Checks for interrupt, returning THROW_IE if interrupted         * before signalled, REINTERRUPT if after signalled, or         * 0 if not interrupted.         */        private int checkInterruptWhileWaiting(Node node) {            return Thread.interrupted() ?                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :                0;        }        /**         * Throws InterruptedException, reinterrupts current thread, or         * does nothing, depending on mode.         */        private void reportInterruptAfterWait(int interruptMode)            throws InterruptedException {            if (interruptMode == THROW_IE)                throw new InterruptedException();            else if (interruptMode == REINTERRUPT)                selfInterrupt();        }        /**         * Implements interruptible condition wait.         * <ol>         * <li> If current thread is interrupted, throw InterruptedException.         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled or interrupted.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * <li> If interrupted while blocked in step 4, throw InterruptedException.         * </ol>         */        public final void await() throws InterruptedException {            if (Thread.interrupted())                throw new InterruptedException();            Node node = addConditionWaiter();            int savedState = fullyRelease(node);            int interruptMode = 0;            while (!isOnSyncQueue(node)) {                LockSupport.park(this);                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)                    break;            }            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)                interruptMode = REINTERRUPT;            if (node.nextWaiter != null) // clean up if cancelled                unlinkCancelledWaiters();            if (interruptMode != 0)                reportInterruptAfterWait(interruptMode);        }        /**         * Implements timed condition wait.         * <ol>         * <li> If current thread is interrupted, throw InterruptedException.         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled, interrupted, or timed out.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * <li> If interrupted while blocked in step 4, throw InterruptedException.         * </ol>         */        public final long awaitNanos(long nanosTimeout)                throws InterruptedException {            if (Thread.interrupted())                throw new InterruptedException();            Node node = addConditionWaiter();            int savedState = fullyRelease(node);            long lastTime = System.nanoTime();            int interruptMode = 0;            while (!isOnSyncQueue(node)) {                if (nanosTimeout <= 0L) {                    transferAfterCancelledWait(node);                    break;                }                LockSupport.parkNanos(this, nanosTimeout);                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)                    break;                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;            }            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)                interruptMode = REINTERRUPT;            if (node.nextWaiter != null)                unlinkCancelledWaiters();            if (interruptMode != 0)                reportInterruptAfterWait(interruptMode);            return nanosTimeout - (System.nanoTime() - lastTime);        }        /**         * Implements absolute timed condition wait.         * <ol>         * <li> If current thread is interrupted, throw InterruptedException.         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled, interrupted, or timed out.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * <li> If interrupted while blocked in step 4, throw InterruptedException.         * <li> If timed out while blocked in step 4, return false, else true.         * </ol>         */        public final boolean awaitUntil(Date deadline)                throws InterruptedException {            if (deadline == null)                throw new NullPointerException();            long abstime = deadline.getTime();            if (Thread.interrupted())                throw new InterruptedException();            Node node = addConditionWaiter();            int savedState = fullyRelease(node);            boolean timedout = false;            int interruptMode = 0;            while (!isOnSyncQueue(node)) {                if (System.currentTimeMillis() > abstime) {                    timedout = transferAfterCancelledWait(node);                    break;                }                LockSupport.parkUntil(this, abstime);                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)                    break;            }            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)                interruptMode = REINTERRUPT;            if (node.nextWaiter != null)                unlinkCancelledWaiters();            if (interruptMode != 0)                reportInterruptAfterWait(interruptMode);            return !timedout;        }        /**         * Implements timed condition wait.         * <ol>         * <li> If current thread is interrupted, throw InterruptedException.         * <li> Save lock state returned by {@link #getState}.         * <li> Invoke {@link #release} with         *      saved state as argument, throwing         *      IllegalMonitorStateException if it fails.         * <li> Block until signalled, interrupted, or timed out.         * <li> Reacquire by invoking specialized version of         *      {@link #acquire} with saved state as argument.         * <li> If interrupted while blocked in step 4, throw InterruptedException.         * <li> If timed out while blocked in step 4, return false, else true.         * </ol>         */        public final boolean await(long time, TimeUnit unit)                throws InterruptedException {            if (unit == null)                throw new NullPointerException();            long nanosTimeout = unit.toNanos(time);            if (Thread.interrupted())                throw new InterruptedException();            Node node = addConditionWaiter();            int savedState = fullyRelease(node);            long lastTime = System.nanoTime();            boolean timedout = false;            int interruptMode = 0;            while (!isOnSyncQueue(node)) {                if (nanosTimeout <= 0L) {                    timedout = transferAfterCancelledWait(node);                    break;                }                if (nanosTimeout >= spinForTimeoutThreshold)                    LockSupport.parkNanos(this, nanosTimeout);                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)                    break;                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;            }            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)                interruptMode = REINTERRUPT;            if (node.nextWaiter != null)                unlinkCancelledWaiters();            if (interruptMode != 0)                reportInterruptAfterWait(interruptMode);            return !timedout;        }        //  support for instrumentation        /**         * Returns true if this condition was created by the given         * synchronization object.         *         * @return {@code true} if owned         */        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {            return sync == AbstractQueuedSynchronizer.this;        }        /**         * Queries whether any threads are waiting on this condition.         * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.         *         * @return {@code true} if there are any waiting threads         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}         *         returns {@code false}         */        protected final boolean hasWaiters() {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {                if (w.waitStatus == Node.CONDITION)                    return true;            }            return false;        }        /**         * Returns an estimate of the number of threads waiting on         * this condition.         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.         *         * @return the estimated number of waiting threads         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}         *         returns {@code false}         */        protected final int getWaitQueueLength() {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            int n = 0;            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {                if (w.waitStatus == Node.CONDITION)                    ++n;            }            return n;        }        /**         * Returns a collection containing those threads that may be         * waiting on this Condition.         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.         *         * @return the collection of threads         * @throws IllegalMonitorStateException if {@link #isHeldExclusively}         *         returns {@code false}         */        protected final Collection<Thread> getWaitingThreads() {            if (!isHeldExclusively())                throw new IllegalMonitorStateException();            ArrayList<Thread> list = new ArrayList<Thread>();            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {                if (w.waitStatus == Node.CONDITION) {                    Thread t = w.thread;                    if (t != null)                        list.add(t);                }            }            return list;        }    }    /**     * Setup to support compareAndSet. We need to natively implement     * this here: For the sake of permitting future enhancements, we     * cannot explicitly subclass AtomicInteger, which would be     * efficient and useful otherwise. So, as the lesser of evils, we     * natively implement using hotspot intrinsics API. And while we     * are at it, we do the same for other CASable fields (which could     * otherwise be done with atomic field updaters).     */    private static final Unsafe unsafe = Unsafe.getUnsafe();    private static final long stateOffset;    private static final long headOffset;    private static final long tailOffset;    private static final long waitStatusOffset;    private static final long nextOffset;    static {        try {            stateOffset = unsafe.objectFieldOffset                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));            headOffset = unsafe.objectFieldOffset                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));            tailOffset = unsafe.objectFieldOffset                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));            waitStatusOffset = unsafe.objectFieldOffset                (Node.class.getDeclaredField("waitStatus"));            nextOffset = unsafe.objectFieldOffset                (Node.class.getDeclaredField("next"));        } catch (Exception ex) { throw new Error(ex); }    }    /**     * CAS head field. Used only by enq.     */    private final boolean compareAndSetHead(Node update) {        return unsafe.compareAndSwapObject(this, headOffset, null, update);    }    /**     * CAS tail field. Used only by enq.     */    private final boolean compareAndSetTail(Node expect, Node update) {        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);    }    /**     * CAS waitStatus field of a node.     */    private static final boolean compareAndSetWaitStatus(Node node,                                                         int expect,                                                         int update) {        return unsafe.compareAndSwapInt(node, waitStatusOffset,                                        expect, update);    }    /**     * CAS next field of a node.     */    private static final boolean compareAndSetNext(Node node,                                                   Node expect,                                                   Node update) {        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);    }}

其中,共享锁源码相关的代码如下:

public static class ReadLock implements Lock, java.io.Serializable {    private static final long serialVersionUID = -5992448646407690164L;    // ReentrantReadWriteLock的AQS对象    private final Sync sync;    protected ReadLock(ReentrantReadWriteLock lock) {        sync = lock.sync;    }    // 获取“共享锁”    public void lock() {        sync.acquireShared(1);    }    // 如果线程是中断状态,则抛出一场,否则尝试获取共享锁。    public void lockInterruptibly() throws InterruptedException {        sync.acquireSharedInterruptibly(1);    }    // 尝试获取“共享锁”    public  boolean tryLock() {        return sync.tryReadLock();    }    // 在指定时间内,尝试获取“共享锁”    public boolean tryLock(long timeout, TimeUnit unit)            throws InterruptedException {        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));    }    // 释放“共享锁”    public  void unlock() {        sync.releaseShared(1);    }    // 新建条件    public Condition newCondition() {        throw new UnsupportedOperationException();    }    public String toString() {        int r = sync.getReadLockCount();        return super.toString() +            "[Read locks = " + r + "]";    }}

说明:
ReadLock中的sync是一个Sync对象,Sync继承于AQS类,即Sync就是一个锁。
ReentrantReadWriteLock中也有一个Sync对象,而且ReadLock中的sync和ReentrantReadWriteLock中的sync是对应关系。即ReentrantReadWriteLock和ReadLock共享同一个AQS对象,共享同一把锁。
ReentrantReadWriteLock中Sync的定义如下:

final Sync sync;
下面,分别从“获取共享锁”和“释放共享锁”两个方面对共享锁进行说明。


获取共享锁

获取共享锁的思想(即lock函数的步骤),是先通过tryAcquireShared()尝试获取共享锁。尝试成功的话,则直接返回;尝试失败的话,则通过doAcquireShared()不断的循环并尝试获取锁,若有需要,则阻塞等待。doAcquireShared()在循环中每次尝试获取锁时,都是通过tryAcquireShared()来进行尝试的。下面看看“获取共享锁”的详细流程。


1. lock()

lock()在ReadLock中,源码如下:

public void lock() {    sync.acquireShared(1);}

2. acquireShared()

Sync继承于AQS,acquireShared()定义在AQS中。源码如下:

public final void acquireShared(int arg) {    if (tryAcquireShared(arg) < 0)        doAcquireShared(arg);}

说明:
acquireShared()首先会通过tryAcquireShared()来尝试获取锁。
尝试成功的话,则不再做任何动作(因为已经成功获取到锁了)。
尝试失败的话,则通过doAcquireShared()来获取锁。doAcquireShared()会获取到锁了才返回。

3. tryAcquireShared()

tryAcquireShared()定义在ReentrantReadWriteLock.java的Sync中,源码如下:

protected final int tryAcquireShared(int unused) {    Thread current = Thread.currentThread();    // 获取“锁”的状态    int c = getState();    // 如果“锁”是“互斥锁”,并且获取锁的线程不是current线程;则返回-1。    if (exclusiveCount(c) != 0 &&        getExclusiveOwnerThread() != current)        return -1;    // 获取“读取锁”的共享计数    int r = sharedCount(c);    // 如果“不需要阻塞等待”,并且“读取锁”的共享计数小于MAX_COUNT;    // 则通过CAS函数更新“锁的状态”,将“读取锁”的共享计数+1。    if (!readerShouldBlock() &&        r < MAX_COUNT &&        compareAndSetState(c, c + SHARED_UNIT)) {        // 第1次获取“读取锁”。        if (r == 0) {             firstReader = current;            firstReaderHoldCount = 1;        // 如果想要获取锁的线程(current)是第1个获取锁(firstReader)的线程        } else if (firstReader == current) {             firstReaderHoldCount++;        } else {            // HoldCounter是用来统计该线程获取“读取锁”的次数。            HoldCounter rh = cachedHoldCounter;            if (rh == null || rh.tid != current.getId())                cachedHoldCounter = rh = readHolds.get();            else if (rh.count == 0)                readHolds.set(rh);            // 将该线程获取“读取锁”的次数+1。            rh.count++;        }        return 1;    }    return fullTryAcquireShared(current);}

说明:
tryAcquireShared()的作用是尝试获取“共享锁”。
如果在尝试获取锁时,“不需要阻塞等待”并且“读取锁的共享计数小于MAX_COUNT”,则直接通过CAS函数更新“读取锁的共享计数”,以及将“当前线程获取读取锁的次数+1”。
否则,通过fullTryAcquireShared()获取读取锁。

4. fullTryAcquireShared()

fullTryAcquireShared()在ReentrantReadWriteLock中定义,源码如下:

final int fullTryAcquireShared(Thread current) {    HoldCounter rh = null;    for (;;) {        // 获取“锁”的状态        int c = getState();        // 如果“锁”是“互斥锁”,并且获取锁的线程不是current线程;则返回-1。        if (exclusiveCount(c) != 0) {            if (getExclusiveOwnerThread() != current)                return -1;        // 如果“需要阻塞等待”。        // (01) 当“需要阻塞等待”的线程是第1个获取锁的线程的话,则继续往下执行。        // (02) 当“需要阻塞等待”的线程获取锁的次数=0时,则返回-1。        } else if (readerShouldBlock()) {            // 如果想要获取锁的线程(current)是第1个获取锁(firstReader)的线程            if (firstReader == current) {            } else {                if (rh == null) {                    rh = cachedHoldCounter;                    if (rh == null || rh.tid != current.getId()) {                        rh = readHolds.get();                        if (rh.count == 0)                            readHolds.remove();                    }                }                // 如果当前线程获取锁的计数=0,则返回-1。                if (rh.count == 0)                    return -1;            }        }        // 如果“不需要阻塞等待”,则获取“读取锁”的共享统计数;        // 如果共享统计数超过MAX_COUNT,则抛出异常。        if (sharedCount(c) == MAX_COUNT)            throw new Error("Maximum lock count exceeded");        // 将线程获取“读取锁”的次数+1。        if (compareAndSetState(c, c + SHARED_UNIT)) {            // 如果是第1次获取“读取锁”,则更新firstReader和firstReaderHoldCount。            if (sharedCount(c) == 0) {                firstReader = current;                firstReaderHoldCount = 1;            // 如果想要获取锁的线程(current)是第1个获取锁(firstReader)的线程,            // 则将firstReaderHoldCount+1。            } else if (firstReader == current) {                firstReaderHoldCount++;            } else {                if (rh == null)                    rh = cachedHoldCounter;                if (rh == null || rh.tid != current.getId())                    rh = readHolds.get();                else if (rh.count == 0)                    readHolds.set(rh);                // 更新线程的获取“读取锁”的共享计数                rh.count++;                cachedHoldCounter = rh; // cache for release            }            return 1;        }    }}

说明:
fullTryAcquireShared()会根据“是否需要阻塞等待”,“读取锁的共享计数是否超过限制”等等进行处理。如果不需要阻塞等待,并且锁的共享计数没有超过限制,则通过CAS尝试获取锁,并返回1。

5. doAcquireShared()

doAcquireShared()定义在AQS函数中,源码如下:

private void doAcquireShared(int arg) {    // addWaiter(Node.SHARED)的作用是,创建“当前线程”对应的节点,并将该线程添加到CLH队列中。    final Node node = addWaiter(Node.SHARED);    boolean failed = true;    try {        boolean interrupted = false;        for (;;) {            // 获取“node”的前一节点            final Node p = node.predecessor();            // 如果“当前线程”是CLH队列的表头,则尝试获取共享锁。            if (p == head) {                int r = tryAcquireShared(arg);                if (r >= 0) {                    setHeadAndPropagate(node, r);                    p.next = null; // help GC                    if (interrupted)                        selfInterrupt();                    failed = false;                    return;                }            }            // 如果“当前线程”不是CLH队列的表头,则通过shouldParkAfterFailedAcquire()判断是否需要等待,            // 需要的话,则通过parkAndCheckInterrupt()进行阻塞等待。若阻塞等待过程中,线程被中断过,则设置interrupted为true。            if (shouldParkAfterFailedAcquire(p, node) &&                parkAndCheckInterrupt())                interrupted = true;        }    } finally {        if (failed)            cancelAcquire(node);    }}

说明:
doAcquireShared()的作用是获取共享锁。
它会首先创建线程对应的CLH队列的节点,然后将该节点添加到CLH队列中。CLH队列是管理获取锁的等待线程的队列。
如果“当前线程”是CLH队列的表头,则尝试获取共享锁;否则,则需要通过shouldParkAfterFailedAcquire()判断是否阻塞等待,需要的话,则通过parkAndCheckInterrupt()进行阻塞等待。
doAcquireShared()会通过for循环,不断的进行上面的操作;目的就是获取共享锁。需要注意的是:doAcquireShared()在每一次尝试获取锁时,是通过tryAcquireShared()来执行的!

shouldParkAfterFailedAcquire(), parkAndCheckInterrupt()等函数已经在“Java多线程系列–“JUC锁”03之 公平锁(一) ”中详细介绍过,这里就不再重复说明了。


释放共享锁

释放共享锁的思想,是先通过tryReleaseShared()尝试释放共享锁。尝试成功的话,则通过doReleaseShared()唤醒“其他等待获取共享锁的线程”,并返回true;否则的话,返回flase。

1. unlock()

public  void unlock() {    sync.releaseShared(1);}

说明:该函数实际上调用releaseShared(1)释放共享锁。

2. releaseShared()

releaseShared()在AQS中实现,源码如下:

public final boolean releaseShared(int arg) {    if (tryReleaseShared(arg)) {        doReleaseShared();        return true;    }    return false;}

说明:
releaseShared()的目的是让当前线程释放它所持有的共享锁。
它首先会通过tryReleaseShared()去尝试释放共享锁。尝试成功,则直接返回;尝试失败,则通过doReleaseShared()去释放共享锁。

3. tryReleaseShared()

tryReleaseShared()定义在ReentrantReadWriteLock中,源码如下:

protected final boolean tryReleaseShared(int unused) {    // 获取当前线程,即释放共享锁的线程。    Thread current = Thread.currentThread();    // 如果想要释放锁的线程(current)是第1个获取锁(firstReader)的线程,    // 并且“第1个获取锁的线程获取锁的次数”=1,则设置firstReader为null;    // 否则,将“第1个获取锁的线程的获取次数”-1。    if (firstReader == current) {        // assert firstReaderHoldCount > 0;        if (firstReaderHoldCount == 1)            firstReader = null;        else            firstReaderHoldCount--;    // 获取rh对象,并更新“当前线程获取锁的信息”。    } else {        HoldCounter rh = cachedHoldCounter;        if (rh == null || rh.tid != current.getId())            rh = readHolds.get();        int count = rh.count;        if (count <= 1) {            readHolds.remove();            if (count <= 0)                throw unmatchedUnlockException();        }        --rh.count;    }    for (;;) {        // 获取锁的状态        int c = getState();        // 将锁的获取次数-1。        int nextc = c - SHARED_UNIT;        // 通过CAS更新锁的状态。        if (compareAndSetState(c, nextc))            return nextc == 0;    }}

说明:
tryReleaseShared()的作用是尝试释放共享锁。

4. doReleaseShared()

doReleaseShared()定义在AQS中,源码如下:

private void doReleaseShared() {    for (;;) {        // 获取CLH队列的头节点        Node h = head;        // 如果头节点不为null,并且头节点不等于tail节点。        if (h != null && h != tail) {            // 获取头节点对应的线程的状态            int ws = h.waitStatus;            // 如果头节点对应的线程是SIGNAL状态,则意味着“头节点的下一个节点所对应的线程”需要被unpark唤醒。            if (ws == Node.SIGNAL) {                // 设置“头节点对应的线程状态”为空状态。失败的话,则继续循环。                if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))                    continue;                // 唤醒“头节点的下一个节点所对应的线程”。                unparkSuccessor(h);            }            // 如果头节点对应的线程是空状态,则设置“文件点对应的线程所拥有的共享锁”为其它线程获取锁的空状态。            else if (ws == 0 &&                     !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))                continue;                // loop on failed CAS        }        // 如果头节点发生变化,则继续循环。否则,退出循环。        if (h == head)                   // loop if head changed            break;    }}

说明:
doReleaseShared()会释放“共享锁”。它会从前往后的遍历CLH队列,依次“唤醒”然后“执行”队列中每个节点对应的线程;最终的目的是让这些线程释放它们所持有的锁。


公平共享锁和非公平共享锁

和互斥锁ReentrantLock一样,ReadLock也分为公平锁和非公平锁。

公平锁和非公平锁的区别,体现在判断是否需要阻塞的函数readerShouldBlock()是不同的。
公平锁的readerShouldBlock()的源码如下:

final boolean readerShouldBlock() {    return hasQueuedPredecessors();}

在公平共享锁中,如果在当前线程的前面有其他线程在等待获取共享锁,则返回true;否则,返回false。
非公平锁的readerShouldBlock()的源码如下:

final boolean readerShouldBlock() {    return apparentlyFirstQueuedIsExclusive();}

在非公平共享锁中,它会无视当前线程的前面是否有其他线程在等待获取共享锁。只要该非公平共享锁对应的线程不为null,则返回true。


ReentrantReadWriteLock示例

import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest1 {     public static void main(String[] args) {         // 创建账户        MyCount myCount = new MyCount("4238920615242830", 10000);         // 创建用户,并指定账户        User user = new User("Tommy", myCount);         // 分别启动3个“读取账户金钱”的线程 和 3个“设置账户金钱”的线程        for (int i=0; i<3; i++) {            user.getCash();            user.setCash((i+1)*1000);        }    } } class User {    private String name;            //用户名     private MyCount myCount;        //所要操作的账户     private ReadWriteLock myLock;   //执行操作所需的锁对象     User(String name, MyCount myCount) {        this.name = name;         this.myCount = myCount;         this.myLock = new ReentrantReadWriteLock();    }    public void getCash() {        new Thread() {            public void run() {                myLock.readLock().lock();                 try {                    System.out.println(Thread.currentThread().getName() +" getCash start");                     myCount.getCash();                    Thread.sleep(1);                    System.out.println(Thread.currentThread().getName() +" getCash end");                 } catch (InterruptedException e) {                } finally {                    myLock.readLock().unlock();                 }            }        }.start();    }    public void setCash(final int cash) {        new Thread() {            public void run() {                myLock.writeLock().lock();                 try {                    System.out.println(Thread.currentThread().getName() +" setCash start");                     myCount.setCash(cash);                    Thread.sleep(1);                    System.out.println(Thread.currentThread().getName() +" setCash end");                 } catch (InterruptedException e) {                } finally {                    myLock.writeLock().unlock();                 }            }        }.start();    }}class MyCount {    private String id;         //账号     private int    cash;       //账户余额     MyCount(String id, int cash) {         this.id = id;         this.cash = cash;     }     public String getId() {         return id;     }     public void setId(String id) {         this.id = id;     }     public int getCash() {         System.out.println(Thread.currentThread().getName() +" getCash cash="+ cash);         return cash;     }     public void setCash(int cash) {         System.out.println(Thread.currentThread().getName() +" setCash cash="+ cash);         this.cash = cash;     } }

运行结果:

Thread-0 getCash startThread-2 getCash startThread-0 getCash cash=10000Thread-2 getCash cash=10000Thread-0 getCash endThread-2 getCash endThread-1 setCash startThread-1 setCash cash=1000Thread-1 setCash endThread-3 setCash startThread-3 setCash cash=2000Thread-3 setCash endThread-4 getCash startThread-4 getCash cash=2000Thread-4 getCash endThread-5 setCash startThread-5 setCash cash=3000Thread-5 setCash end

结果说明:
(01) 观察Thread0和Thread-2的运行结果,我们发现,Thread-0启动并获取到“读取锁”,在它还没运行完毕的时候,Thread-2也启动了并且也成功获取到“读取锁”。
因此,“读取锁”支持被多个线程同时获取。

(02) 观察Thread-1,Thread-3,Thread-5这三个“写入锁”的线程。只要“写入锁”被某线程获取,则该线程运行完毕了,才释放该锁。
因此,“写入锁”不支持被多个线程同时获取。

本文From:http://www.cnblogs.com/skywang12345/p/3505809.html

0 0
原创粉丝点击