ReentrantReadWriteLock中文Javadoc及部分代码解读

package java.util.concurrent.locks;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.lang.reflect.Field;
import java.util.Collection;

/**
 * 这是接口{@link ReadWriteLock}的实现类,支持类似于{@link ReentrantLock}的语义. 
 * <p>这个类具有下面的属性:
 *
 * <ul>
 * <li><b>锁获取顺序</b>
 *
 * <p>这个类不受锁访问的读写锁偏好顺序影响.然而,它支持可选的<em>公平(fairness)</em>策略.
 *
 * <dl>
 * <dt><b><i>非公平模式(Non-fair mode) (默认)</i></b>
 * <dd>当构造为非公平锁(默认)时, 读锁和写锁的进入顺序是未指定的,受限于可重入性约束.
 * 竞争非公平锁可能会无限期延迟一个或多个读线程或写线程,但通常比公平锁有更高的吞吐量.
 *
 * <dt><b><i>公平模式(Fair mode)</i></b>
 * <dd>当构造为公平锁时,线程竞争使用近似于到达顺序(arrival-order)策略.
 * 当释放当前持有的锁时,要么等待时间最长的写线程被分配写锁,要么一组比所有等待写线程等待时间都长的读线程被分配读锁.
 *
 * <p>如果写锁被持有或者存在等待写线程,尝试获取公平的读锁(不可重入)的线程会阻塞.
 * 这个线程不会获得读锁,直到当前最老的等待写线程获得写锁并释放.当然,如果某个等待写
 * 线程放弃等待,一个或多个读线程成为队列中等待写锁释放的时间最长的线程,那么读线程都将被分配读锁.
 *
 * <p>尝试获取公平的写入锁(不可重入)的线程将会被阻塞,除非读锁和写锁都是自由状态(这隐含着没有等待线程).(注意非阻塞的{@link ReadLock#tryLock()}和{@link WriteLock#tryLock()}方法不受公平设置的影响,如果可能的话,不管是否有等待线程这两个方法都会立即获得锁.
 * <p>
 * </dl>
 *
 * <li><b>可重入性(Reentrancy)</b>
 *
 * <p>这个锁允许读锁和写锁以{@link ReentrantLock}方式重新获取读锁或写锁.
 * 不可重入的读线程不被允许,直到写线程持有的所有写锁都被释放.
 *
 * <p>此外,写线程可以获取读锁,但反之不行.在一些应用中,可重入性是很有用的,如当在持有写锁时
 * 调用执行在读锁下的读操作的方法.如果读线程尝试获取写锁,它永远也不会成功.
 *
 * <li><b>锁降级(Lock downgrading)</b>
 * <p>可重入性也允许从写锁降级为读锁,先获取写锁,然后获取读锁,再然后释放写锁.
 * 然而,从读锁升级为写锁是<b>不可能的</b>.
 *
 * <li><b>锁获取中断</b>
 * <p>读锁和写锁都支持在锁获取过程中中断.
 *
 * <li><b>{@link Condition}支持</b>
 * <p>写锁提供了{@link Condition}实现,它的行为与{@link ReentrantLock#newCondition}提供的 {@link Condition}实现相同
 * 这个{@link Condition}当然只能用于写锁.
 *
 * <p>读锁不支持{@link Condition},调用{@code readLock().newCondition()}会抛出{@code UnsupportedOperationException}.
 *
 * <li><b>仪器(Instrumentation)</b>
 * <p>这个类支持确定是否锁被持有或被竞争的方法.这些方法用于监视系统状态,不用于同步控制.
 * </ul>
 *
 * <p>这个类的序列化行为与内置的锁相同:反序列化得到的锁处于未锁定状态,不管序列化时是什么状态.
 *
 * <p><b>用法示例</b>. 下面是一个代码骨架,演示了如何在更新缓存之后执行锁降级(
 * 当以非嵌套方式处理多个锁时,异常处理需要一些特殊的技巧:
 *
 * <pre> {@code
 * class CachedData {
 *   Object data;
 *   volatile boolean cacheValid;
 *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
 *
 *   void processCachedData() {
 *     rwl.readLock().lock();
 *     if (!cacheValid) {
 *       // 在获取写锁之前必须释放读锁
 *       rwl.readLock().unlock();
 *       rwl.writeLock().lock();
 *       try {
 *         // 重新检查状态,因为另一个线程可能获取了写锁并在我们之前修改了状态.
 *         if (!cacheValid) {
 *           data = ...
 *           cacheValid = true;
 *         }
 *         // 在释放写锁之前获取读锁进行降级
 *         rwl.readLock().lock();
 *       } finally {
 *         rwl.writeLock().unlock(); // 释放写锁,仍然持有读锁
 *       }
 *     }
 *
 *     try {
 *       use(data);
 *     } finally {
 *       rwl.readLock().unlock();
 *     }
 *   }
 * }}</pre>
 *
 * ReentrantReadWriteLocks可以用于提升一些集合使用场景的并发性. 
 * 这通常只在集合很大,且访问它的读线程比写线程多,需要使用开销大于同步开销的操作时是有用的.
 * 例如,下面是一个使用很大的TreeMap且并发访问的类.
 *
 *  <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>实现注意事项</h3>
 *
 * <p>这个锁支持最大65535个递归写锁和65535个读锁。尝试超过这些限制将导致在锁定方法中抛出{@link Error}.
 *
 * @since 1.5
 * @author Doug Lea
 */
public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    /** 内部类,提供读锁 */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** 内部类,提供写锁 */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    /** 执行所有的同步机制 */
    final Sync sync;

    /**
     * 创建具有默认排序属性(非公平)的新{@code ReentrantReadWriteLock}实例.
     */
    public ReentrantReadWriteLock() {
        this(false);
    }

    /**
     * 创建具有给定的公平策略的新{@code ReentrantReadWriteLock}实例.
     *
     * @param fair {@code true} 如果这个锁应该使用公平排序策略
     */
    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; }

    /**
     * ReentrantReadWriteLock的同步实现. 创建的子类有公平版本和非公平版本.
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 6317671515068378041L;

        /*
         * 读与写锁的数量提取常量和函数.
         * 锁定状态逻辑上分为两个无符号短整型(unsigned shorts):
         * 较低的整型表示独占(写)锁的持有数量,
         * 较高的整型表示共享(读)锁的持有数量.
         */

        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;

        /** 返回count中表示共享锁持有的数量  */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        /** 返回count中表示独占锁持有的数量  */
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

        /**
         * 用于每一个线程读锁持有数量的计算器.
         * 用ThreadLocal维护; 缓存到cachedHoldCounter
         */
        static final class HoldCounter {
            int count = 0;
            // 使用线程的id, 而不是引用, 避免垃圾保留
            final long tid = getThreadId(Thread.currentThread());
        }

        /**
         * ThreadLocal子类. 显示定义反序列化机制.
         */
        static final class ThreadLocalHoldCounter
            extends ThreadLocal<HoldCounter> {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        /**
         * 当前线程持有的可重入读锁的数量.
         * 只在构造器和readObject中初始化.
         * 当线程的读锁持有数量减小到0时,要移除.
         */
        private transient ThreadLocalHoldCounter readHolds;

        /**
         * 成功获取读锁的最后一个线程的持有数量.
         * 在通常情况下,下一个要释放的线程是最后一个要获取的线程,这样做可以节省ThreadLocal查找时间.
         * 这是非易失性的,因为它只是用作启示规则,非常适合线程缓存.
         *
         * <p>可以延长线程的存活时间,它缓存了读锁持有数量, 但是可以通过不保留线程的引用避免垃圾保留.
         *
         * <p>通过良性的数据竞争访问; 依赖内存模型的final字段和out-of-thin-air(无中生有)保证.
         */
        private transient HoldCounter cachedHoldCounter;

        /**
         * firstReader是第一个获取读锁的线程.
         * firstReaderHoldCount是firstReader的持有数量.
         *
         * <p>更准确地说,firstReader是最后一个将共享数量从0改为1的唯一线程, 且从此没有释放过读锁.
         * 如果没有这样的线程,那么它的值为null.
         *
         * <p>不能导致垃圾保留,除非线程终止时没有释放读锁,由于tryReleaseShared将它设置为null.
         *
         * <p>通过良性的数据竞争访问;依赖内存模型的(无中生有)out-of-thin-air保证引用.
         *
         * <p>这使得跟踪非争用读锁的读持有数量代价很小.
         */
        private transient Thread firstReader = null;
        private transient int firstReaderHoldCount;

        Sync() {
            readHolds = new ThreadLocalHoldCounter();
            setState(getState()); // ensures visibility of readHolds
        }

        /*
         * 公平锁和非公平锁的获取和释放使用相同的代码.
         * 但是不同点在于,当队列非空时,是否/如何允许闯入(抢占)(barging).
         */

        /**
         * 如果当前线程尝试获取读锁且其它线程有资格这样做, 那么当前线程应该阻塞.
         * 因为策略是超过其它等待线程.
         */
        abstract boolean readerShouldBlock();

        /**
         * 如果当前线程尝试获取写锁且其它线程有资格这样做,那么当前线程应该阻塞.
         * 因为策略是超过其它等待线程.
         */
        abstract boolean writerShouldBlock();

        /*
         * 注意tryRelease和tryAcquire可以被Condition调用.
         * 所以有可能它们的参数包含Condition等待过程中释放的和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) {
        	/*
             * 代码流程:
             * 1. 如果读锁持有数量非零或者写锁持有数量非零,且锁拥有者不是当前线程,则获取失败.
             * 2. 如果count已经饱和(达到最大值)(这只可能发生在count已经非零的情况)
             * 3. 否则,这个线程有资格获取这个锁,如果它是一个可重入获取或者排队策略允许.如果是这样,更新state状态,并将当前线程设置为owner.
             */
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);
            // c不为0,说明已经有线程持有读锁或者写锁
            if (c != 0) {
            	// (注意: if c != 0 and w == 0 那么共享锁的count != 0)
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                // 如果获取锁后的读占锁的数量大于最大数量,则报Error,超过最大锁数量
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 可重入获取写锁
                setState(c + acquires);
                return true;
            }
            // 如果c为0,说明没有线程持有读锁或者写锁
            // 如果写线程需要阻塞,或者修改state状态失败,则获取失败
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            // 如果写线程不需要阻塞,且修改state状态成功,则将当前线程设置为owner
            setExclusiveOwnerThread(current);
            // 返回获取锁成功
            return true;
        }

        protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            // 如果当前线程是第一个获取共享锁的线程,即firstReader
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--;
            } else {
            	// 如果缓存的holder不存在,或者属于当前线程,则从readHolds中查找
                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                // 如果count已经是1或者0了,那么直接从readHolds删除对应的线程记录
                if (count <= 1) {
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                // 将当前线程持有读锁的数量减1
                --rh.count;
            }
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT;
                if (compareAndSetState(c, nextc))
                	// 释放读锁对读线程没有影响,
                    // 但是如果读写锁都空闲的话,可能允许等待的写线程继续执行
                	// nextc等于0表示当前已经没有读线程占用共享锁,写线程可以获取独占锁了
                    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) {
            /*
             * 代码流程:
             * 1. 如果另一个线程持有写锁,那么该方法获取共享锁失败.
             * 2. 否则,该线程就有资格锁定wrt状态,所以根据队列策略判断是否应该阻塞.
             *    如果不需要阻塞,尝试比较并交换state状态,并更新锁持有数量.
             *    注意,这一步没有检查可重入获取读锁,这被推迟到完全版本,
             *    以避免在更多典型的非重入场景下检查持有数量.
             * 3. 如果步骤2失败,可能因为线程明确没有资格(需要阻塞等待),或CAS失败(其它线程并发修改),
             *    或共享锁持有数量饱和(锁持有数量达到最大值65535),则进入完全重试循环版本.
             */
            Thread current = Thread.currentThread();
            int c = getState();
            // 如果另一个线程持有写锁, 即独占锁数量不等于0且不是当前线程,那么该方法获取共享锁失败
            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) {
                	// 第一个线程可重入的获取读锁,读锁持有数量加1
                    firstReaderHoldCount++;
                } else {
                	// 成功获取读锁的最后一个线程的持有数量.
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            return fullTryAcquireShared(current);
        }

        /**
         * 获取读锁的完全版本, 处理CAS丢失,可重入读锁,这些都没有在tryAcquireShared中处理.
         */
        final int fullTryAcquireShared(Thread current) {
            /*
             * 这部分代码相对于tryAcquireShared有点冗余,
             * 但是总的来说,它简化了tryAcquireShared与重试和延迟读取持有数量的交互.
             */
            HoldCounter rh = null;
            for (;;) {
                int c = getState();
                if (exclusiveCount(c) != 0) {
                    if (getExclusiveOwnerThread() != current)
                        return -1;
                    // 否则如果是当前线程持有独占锁,在这里阻塞将导致死锁.
                } else if (readerShouldBlock()) {
                    // 确保当前线程没有重入获取读锁
                    if (firstReader == current) {
                        // assert firstReaderHoldCount > 0;
                    } else {
                        if (rh == null) {
                            rh = cachedHoldCounter;
                            if (rh == null || rh.tid != getThreadId(current)) {
                                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 != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        cachedHoldCounter = rh; // cache for release
                    }
                    return 1;
                }
            }
        }

        /**
         * 尝试获取写锁, 在两种模式下使能barging.
         * 该方法与tryAcquire效果是相同的,除了没有调用writerShouldBlock外.
         */
        final boolean tryWriteLock() {
            Thread current = Thread.currentThread();
            int c = getState();
            // state状态不等于0表示已经有其它线程持有写锁或者读锁
            if (c != 0) {
            	// 获取独占锁的数量
                int w = exclusiveCount(c);
                // 独占锁的数量等于0,或者独占的线程不是当前线程,则返回false,表示获取写锁失败
                // 如果w == 0表示同步器Sync的读锁被其它线程持有,而读写锁要互斥,因此写锁获取失败
                // 如果current != getExclusiveOwnerThread()表示已经有其它线程持有写锁了,而写锁与写锁要互斥,因此写锁获取失败
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                // 如果当前线程是该写锁的独占线程,且锁持有数量达到最大的65535, 则报Error错误
                if (w == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
            }
            // state状态等于0表示没有其它线程持有写锁或者读锁,那么将state状态加1
            if (!compareAndSetState(c, c + 1))
                return false; // 如果有其它线程并发获取了写锁或读锁,则当前线程获取写锁失败
            // 将当前线程设置为该写锁的独占拥有者线程
            setExclusiveOwnerThread(current);
            // 返回当前线程获取写锁成功
            return true;
        }

        /**
         * 执行尝试获取读锁,使能在共享模式和独占模式下的闯入(抢占)(barging).
         * 该方法与tryAcquireShared效果是相同的,除了没有调用readerShouldBlock.
         */
        final boolean tryReadLock() {
            Thread current = Thread.currentThread();
            for (;;) {
                int c = getState();
                // 如果独占锁(写锁)被其它线程持有且当前线程不是独占锁拥有者线程,则获取共享锁(读锁)失败
                if (exclusiveCount(c) != 0 &&
                    getExclusiveOwnerThread() != current)
                    return false;
                // 获取共享锁的使用数量
                int r = sharedCount(c);
                // 如果共享锁数量的达到最大值65535,则报Error
                if (r == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // CAS占用共享锁,如果有其它读线程也在获取共享锁,则下面的if的测试条件有可能为false
                // 需要执行for循环再次尝试获取共享锁,只要共享锁可用,则一定可以获取成功
                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 != getThreadId(current))
                            cachedHoldCounter = rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                    }
                    // 返回true,表示尝试获取读锁成功
                    return true;
                }
            }
        }

        protected final boolean isHeldExclusively() {
            // 我们通常必须在获取拥有者之前读取state状态, 我们无需检查当前线程是否是拥有者
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        // Methods relayed to outer class

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        final Thread getOwner() {
            // 获取owner之前必须读取state状态,确保内存一致性
        	// 首先判断是否有线程持有独占锁,有线程持有独占锁的数量不为0,则返回独占拥有者线程,否则返回null
            return ((exclusiveCount(getState()) == 0) ? 
                    null :
                    getExclusiveOwnerThread());
        }

        final int getReadLockCount() {
        	// 共享锁的持有数量
            return sharedCount(getState());
        }

        final boolean isWriteLocked() {
        	// 独占锁的持有数量不为0,就表示写锁是被锁定的
            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 == getThreadId(current))
                return rh.count;

            int count = readHolds.get().count;
            if (count == 0) readHolds.remove();
            return count;
        }

        /**
         * 从流中重新构造该实例,即反序列化.
         */
        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(); }
    }

    /**
     * Sync的非公平版本
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // 写线程总是可以闯入(抢占)barge
        }
        
        final boolean readerShouldBlock() {
        	/*
        	 * 为了避免写线程无限期饥饿, 如果暂时出现在等待队列的头结点的线程(如果存在的话)是一个等待中的写线程,
        	 * 那么当前读线程阻塞.
        	 * 这只是一个随机的效果,因为在等待队列中,如果等待的写线程排在其它读线程之后,那么新的读线程不会阻塞.
        	 */
            return apparentlyFirstQueuedIsExclusive();
        }
    }

    /**
     * Sync的公平版本
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

    /**
     * {@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 外部锁对象
         * @throws NullPointerException 如果lock是null
         */
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        /**
         * 获取读锁.
         *
         * <p>如果写锁没有被另一个线程持有,那么就获得读锁,并立即返回.
         *
         * <p>如果写锁被另一个线程持有,那么当前线程就会被禁止调度,休眠直到获取到读锁.
         */
        public void lock() {
            sync.acquireShared(1);
        }

        /**
         * 获取读锁,除非当前线程被中断{@linkplain Thread#interrupt interrupted}.
         *
         * <p>如果写锁没有被另一个线程持有,那么就获得读锁,并立即返回.
         *
         * <p>如果写锁被另一个线程持有,那么当前线程就会被禁止调度,休眠直到发生下面的事情之一:
         * 
         * <ul>
         *
         * <li>当前线程获得读锁
         *
         * <li>其它线程中断{@linkplain Thread#interrupt interrupts}当前线程.
         *
         * </ul>
         *
         * <p>如果当前线程:
         *
         * <ul>
         *
         * <li>在进入该方法时设置了中断状态
         *
         * <li>获取读锁时被中断{@linkplain Thread#interrupt interrupted}
         *
         * </ul>
         *
         * 那么该线程会抛出{@link InterruptedException}中断异常,当前线程的中断状态被清除.
         *
         * <p>在这个实现中,由于该方法是一个明确的中断点,所以会优先响应中断,而不是优先获取锁.
         *
         * @throws InterruptedException 如果当前线程被中断
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }

        /**
         * 在调用该方法时,写锁没有被另一个线程持有,那么就获得读锁.
         *
         * <p>如果写锁没有被另一个线程持有,那么该方法获取读锁,并立即返回true.
         * 即使当这个锁设置使用公平的排序策略,调用{@code tryLock()}也
         * <em>将</em>立即获取读锁,只要读锁可用,不管是否有其它的线程正在等待读锁.
         * 这种&quot;闯入(抢占)(barging)&quot;行为在特定场景下是很有用的, 即使它破坏了公平性.
         * 如果你想要尊重公平性设置,那么使用{@link #tryLock(long, TimeUnit)
         * tryLock(0, TimeUnit.SECONDS) },几乎是等价的(它也检测中断).
         *
         * <p>如果写锁被另一个线程持有,那么该方法会立即返回{@code false}.
         *
         * @return {@code true} 如果获得了读锁,则返回true
         */
        public boolean tryLock() {
            return sync.tryReadLock();
        }

        /**
         * 如果在给定的等待时间内,没有另一个线程持有写锁,且当前线程没有被中断,那么就获得读锁.
         *
         * <p>如果写锁没有被另一个线程持有,那么该方法获取读锁,并立即返回true.
         * 如果这个锁被设置使用公平的排序策略,那么如果有其它线程也在等待这个锁,那么当前线程不会获得锁.
         * 这与{@link #tryLock()}方法时相反的.
         * 如果你想要的一个限时的{@code tryLock},且允许在公平锁上的闯入(抢占),那么可以将限时和不限时形式组合在一起使用.
         *
         *  <pre> {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}</pre>
         *
         * <p>如果写锁被另一个线程持有,那么当前线程就被禁止线程调度,休眠直到下列三件事之一发生:
         *
         * <ul>
         *
         * <li>当前线程获得读锁
         *
         * <li>其它线程中断当前线程
         *
         * <li>指定的等待时间已经过了
         *
         * </ul>
         *
         * <p>如果获得了读锁,则返回{@code true}.
         *
         * <p>如果当前线程:
         *
         * <ul>
         *
         * <li>在进入该方法时设置了中断状态
         *
         * <li>或者在获取读锁时被中断
         *
         * </ul> 那么当前线程抛出{@link InterruptedException}中断异常,当前线程的中断状态被清除.
         *
         * <p>如果指定的超时时间已经过了,那么返回{@code false}.
         * 如果时间小于等于0,那么该方法不会执行等待.
         *
         * <p>在这个实现中,由于该方法是明确的中断点,所以优先响应中断,
         * 而不是优先获取读锁或者报告等待超时.
         *
         * @param timeout 等待读锁的超时时间
         * @param unit 超时参数的时间单位
         * @return {@code true} 如果获得了读锁,则返回true
         * @throws InterruptedException 如果当前线程被中断
         * @throws NullPointerException 如果时间单位是null
         */
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }

        /**
         * 尝试释放读锁.
         *
         * <p>如果读线程数量限制是0,那么写锁可以尝试使用.
         */
        public void unlock() {
            sync.releaseShared(1);
        }

        /**
         * 抛出{@code UnsupportedOperationException}异常,因为{@code ReadLocks}不支持条件.
         *
         * @throws UnsupportedOperationException 总是抛出
         */
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }

        /**
         * 返回这个锁的字符串标识,包括它的锁的状态.
         * 在方括号里,状态,包括字符串{@code "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 + "]";
        }
    }

    /**
     * {@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 外部的锁对象
         * @throws NullPointerException 如果lock是null
         */
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        /**
         * 获取写锁.
         *
         * <p>如果没有另一个线程持有读锁或者写锁,那么就获取写锁,设置写锁持有数量为1, 并立即返回.
         *
         * <p>如果当前线程已经持有这个写锁,那么写锁持有数量会增加1,该方法立即返回.
         *
         * <p>如果写锁被另一个线程持有,那么当前线程禁止参与线程调度,并阻塞,直到写锁被释放,此时写锁持有数量设置为1.
         */
        public void lock() {
            sync.acquire(1);
        }

        /**
         * 获取写锁,除非当前线程被中断({@linkplain Thread#interrupt interrupted}).
         *
         * <p>如果没有另一个线程持有读锁或者写锁,那么就获取写锁,设置写锁持有数量为1, 并立即返回.
         *
         * <p>如果当前线程已经持有这个写锁,那么写锁持有数量会增加1,该方法立即返回.
         *
         * <p>如果写锁被另一个线程持有,那么当前线程禁止参与线程调度,并阻塞,直到下面两件事情之一发生:
         *
         * <ul>
         *
         * <li>当前线程获得写锁
         *
         * <li>其它线程中断了当前线程{@linkplain Thread#interrupt interrupts}
         *
         * </ul>
         *
         * <p>如果当前线程获得写锁,那么锁持有数量设置为1.
         *
         * <p>如果当前线程:
         *
         * <ul>
         *
         * <li>在进入该方法时设置了中断状态
         * or
         *
         * <li>或者正在获取写锁时被中断{@linkplain Thread#interrupt interrupted}
         *
         * </ul>
         *
         * 那么就会抛出{@link InterruptedException},当前线程中断状态被清除.
         *
         * <p>在这个实现中,由于该方法是明确的中断点,所以优先响应中断,还不是优先正常的或重入地获取该锁.
         *
         * @throws InterruptedException 如果当前线程被中断
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }

        /**
         * 只有在调用该方法时没有另一个线程持有该写锁才获得这个写锁.
         *
         * <p>如果没有另一个线程持有读锁或写锁,那么该方法就获得写锁,并立即返回{@code true},
         * 设置写锁持有数量为1. 如果锁可用的话,即使这个锁使用的是公平排序策略,调用{@code tryLock()}也<em>将</em>立即获取锁,
         * 不管当前是否有其它线程正在等待写锁. 在特定场景下,这种&quot;闯入(抢占)barging&quot;是很有用的,即使它破坏了公平性.
         * 如果你想要尊重该锁的公平性设置,那么使用{@link#tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) },
         * 这个方法是等价的(它也会检测中断).
         *
         * <p>如果当前线程已经持有该锁,那么持有数量会加1,该方法返回{@code true}.
         *
         * <p>如果另一个线程持有该锁,那么这个方法会立即返回{@code false}.
         *
         * @return {@code true} 如果该锁空闲并曾被当前线程获取过,或者当前线程已经获取了该写锁,则返回true;否则返回false.
         */
        public boolean tryLock( ) {
            return sync.tryWriteLock();
        }

        /**
         * 如果在给定的等待时间内没有另一个线程持有写锁,且当前线程没有被中断,则获得写锁.
         *
         * <p>如果其它线程既没有持有读锁,也没有持有写锁,那么就获得写锁,并立即返回{@code true}.
         * 设置写锁持有数量为1.
         * 如果这个锁设置使用公平的排序策略,那么有其它的线程正在等待写锁,那么当前线程也不会获得这个可用的锁.
         * 这与{@link #tryLock()}方法相反.如果你想要一限时的{@code tryLock},且允许在公平锁上闯入(抢占),
         * 如果你想要的一个限时的{@code tryLock},且允许在公平锁上的闯入(抢占),那么可以将限时和不限时形式组合在一起使用:
         *
         *  <pre> {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}</pre>
         *
         * <p>如果当前线程已经持有这个锁,那么持有数量加1,该方法返回{@code true}.
         *
         * <p>如果这个锁被另一个线程持有,那么当前线程将被禁止线程调度,休眠直到下面的三件事情之一发生:
         *
         * <ul>
         *
         * <li>当前线程获得了写锁
         *
         * <li>或者其它线程中断了当前线程
         *
         * <li>指定的等待超时时间过了
         *
         * </ul>
         *
         * <p>如果获得了写锁,那么该方法返回{@code true},写锁持有数量设置为1.
         *
         * <p>如果当前线程:
         *
         * <ul>
         *
         * <li>在进入该方法时设置了中断状态
         *
         * <li>或者正在获取写锁时被中断{@linkplain Thread#interrupt interrupted}
         *
         * </ul>
         *
         * 那么就会抛出{@link InterruptedException},当前线程中断状态被清除.
         *
         * <p>在这个实现中,由于该方法是明确的中断点,所以优先响应中断,还不是优先正常的或重入地获取该锁.
         *
         * <p>如果指定的超时时间已经过了,那么返回{@code false}.
         * 如果时间小于等于0,那么该方法不会执行等待.
         *
         * <p>在这个实现中,由于该方法是明确的中断点,所以优先响应中断,
         * 而不是优先获取锁或者报告等待超时.
         * 
         * @param timeout 等待写锁的超时时间
         * @param unit timeout参数的时间单位
         *
         * @return {@code true} 如果锁时空闲的,且被当前线程获取了,则返回true;
         *         或者写锁已经被当前线程持有;如果在获得锁之前超时了,那么返回{@code false}
         *
         * @throws InterruptedException 如果当前线程被中断
         * @throws NullPointerException 如果时间单位是null
         */
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }

        /**
         * 尝试释放这个锁.
         *
         * <p>如果当前线程是这个锁的持有者,那么持有数量减1.
         * 如果持有数量现在是0,那么释放这个锁.
         * 如果当前线程不是这个锁的持有者,那么抛出 {@link IllegalMonitorStateException}异常.
         *
         * @throws IllegalMonitorStateException 如果当前线程不持有该锁
         */
        public void unlock() {
            sync.release(1);
        }

        /**
         * 返回一个{@link Condition}实例,
         * <p>返回的{@link Condition}实例支持的用法类似于内置监视器锁中使用的{@link Object} 监视器方法 ({@link
         * Object#wait() wait}, {@link Object#notify notify}, 和 {@link
         * Object#notifyAll notifyAll}).
         * 
         * <ul>
         *
         * <li>如果该写锁没有被任何线程持有,那么调用该{@link Condition}上的方法会抛出{@link
         * IllegalMonitorStateException}异常.  
         * (读锁被持有与写锁是独立的,所以不受检查, 不影响。不过,当当前线程也获得了读锁时,
         * 调用condition的wait方法有必要总是一个错误,因为其它可以解锁读锁的线程将不能获取写锁).
         *
         * <li>当调用condition {@linkplain Condition#await() waiting}方法时,写锁被释放,
         * 在它们返回之前,写锁又重新获取,锁持有数量恢复到调用await方法时的数量.
         *
         * <li>如果在等待时线程被中断,那么等待也被终止,并抛出中断异常,线程的中断状态被清除.
         *
         * <li> 等待线程按照先进先出(FIFO)顺序通知.
         *
         * <li>从waiting方法返回后的线程获取锁的顺序与这些线程初始获取锁的顺序相同,这是默认的场景. 
         * 但是对于 <em>公平</em>锁,更优先考虑等待时间最长的线程.
         *
         * </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();
        }
    }

    // 测试与状态

    /**
     * 如果公平性设置为true,则返回{@code true}.
     *
     * @return {@code true} if this lock has fairness set true
     */
    public final boolean isFair() {
        return sync instanceof FairSync;
    }

    /**
     * 返回当前拥有写锁的线程,如果没有线程拥有写锁,则返回{@code null}.
     * 当该方法由不是拥有者的线程调用时,返回的值反映的是当前锁状态的近似值.
     * 例如,即使有线程正在尝试获取锁,但是还没有得到.When this method is called by a
     * 设计该方法时为了帮助构造子类,以提供更多的锁监控工具.
     *
     * @return the owner, or {@code null} if not owned
     */
    protected Thread getOwner() {
        return sync.getOwner();
    }

    /**
     * 查询为该锁持有的读锁的数量. 这个方法设计的目的是用于监控系统状态,不用于同步控制.
     * @return 持有的读锁的数量
     */
    public int getReadLockCount() {
        return sync.getReadLockCount();
    }

    /**
     * 查询是否写锁被某个线程持有. 这个方法设计的目的是用于监控系统状态,不用于同步控制.
     *
     * @return {@code true} if any thread holds the write lock and
     *         {@code false} otherwise
     */
    public boolean isWriteLocked() {
        return sync.isWriteLocked();
    }

    /**
     * 查询是否写锁被当前线程持有.
     *
     * @return 如果当前先吃持有写锁, 返回{@code true} , 否则,返回{@code false}
     */
    public boolean isWriteLockedByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /**
     * 查询当前线程持有该锁上的可重入写锁的数量.
     * 写线程为每一个未匹配unlock动作的lock动作持有一个锁.
     *
     * @return 当前线程持有的写锁的数量,如果当前线程没有持有写锁,则返回0
     */
    public int getWriteHoldCount() {
        return sync.getWriteHoldCount();
    }

    /**
     * 查询当前线程持有该锁上的可重入读锁的数量.
     * 读线程为每一个未匹配unlock动作的lock动作持有一个锁.
     *
     * @return 当前线程持有的读锁的数量,如果当前线程没有持有读锁,则返回0
     * @since 1.6
     */
    public int getReadHoldCount() {
        return sync.getReadHoldCount();
    }

    /**
     * 返回一个包含等待获取写锁的线程集合.
     * 因为实际的线程集可能会在构造这个结果时动态改变,所以返回的集合只是一个最优估计值.
     * 返回集合中的元素是没有特定顺序的. 设计该方法是为了帮助构造子类以提供更多锁监控工具.
     *
     * @return 线程集合Collection
     */
    protected Collection<Thread> getQueuedWriterThreads() {
        return sync.getExclusiveQueuedThreads();
    }

    /**
     * 返回一个包含等待获取读锁的线程集合.
     * 因为实际的线程集可能会在构造这个结果时动态改变,所以返回的集合只是一个最优估计值.
     * 返回集合中的元素是没有特定顺序的. 设计该方法是为了帮助构造子类以提供更多锁监控工具.
     * 
     * @return 线程集合Collection
     */
    protected Collection<Thread> getQueuedReaderThreads() {
        return sync.getSharedQueuedThreads();
    }

    /**
     * 查询是否有某个线程正在等待获取读锁或者写锁.
     * 注意,由于可能在任意时刻取消等待, 因此返回true不保证有其它线程已经获取到了锁.
     * 这个方法主要用于监控系统状态.
     *
     * @return {@code true} 如果有其它线程正在等待获取锁
     */
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    /**
     * 查询是否给定的线程正在等待获取读锁或者写锁.
     * 注意,由于可能在任意时刻取消等待, 因此返回true不保证有这个线程已经获取到了锁.
     * 这个方法主要用于监控系统状态.
     *
     * @param thread the thread
     * @return {@code true} 如果有thread线程正在等待获取锁
     * @throws NullPointerException if the thread is null
     */
    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    /**
     * 返回等待获取读锁或写锁的线程的数量的估计值.
     * 返回的值只是一个估计值,因为在这个方法遍历内部数据结构时,线程数量可能会动态变化.
     * 这个方法设计的目的是用于监控系统状态,不用于同步控制.
     *
     * @return 等待这个锁的线程数量的估计值
     */
    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    /**
     * 返回可能包含等待获取读锁或写锁的线程的集合.
     * 因为实际的线程集可能会在构造这个结果时动态改变,所以返回的集合只是一个最优估计值.
     * 返回集合中的元素是没有特定顺序的. 设计该方法是为了帮助构造子类以提供更多锁监控工具.
     *
     * @return the collection of threads
     */
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    /**
     * 查询是否有线程正在等待给定的与写锁有关的条件.
     * 注意,因为超时和中断可能随时发生,返回true不保证将来的signal会唤醒任何线程.
     * 这个方法设计的目的是用于监控系统状态.
     *
     * @param condition the condition
     * @return {@code true} 如果没有任何等待的线程
     * @throws IllegalMonitorStateException 如果没有持有这个锁
     * @throws IllegalArgumentException 如果给定的条件与这个锁无关
     * @throws NullPointerException 如果condition是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);
    }

    /**
     * 返回等待与写锁有关的条件的线程的数量的估计值.
     * 等待给定的与写锁有.
     * 注意,因为超时和中断可能随时发生,这个估计值只是实际等待线程数量的上限.
     * 这个方法设计的目的是用于监控系统状态,不用于同步控制.
     *
     * @param condition the condition
     * @return 等待线程的估计数量
     * @throws IllegalMonitorStateException 如果没有持有这个锁
     * @throws IllegalArgumentException 如果给定条件与这个锁无关
     * @throws NullPointerException 如果condition是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);
    }

    /**
     * 返回包含等待与写锁有关的条件的线程的集合.
     * 因为实际的线程集可能会在构造这个结果时动态改变,所以返回的集合只是一个最优估计值.
     * 设计该方法是为了帮助构造子类以提供更多condition监控工具.
     *
     * @param condition the condition
     * @return 线程集合
     * @throws IllegalMonitorStateException 如果这个锁没有持有
     * @throws IllegalArgumentException 如果给定的条件与这个锁无关
     * @throws NullPointerException 如果condition是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);
    }

    /**
     * 返回一个字符串标识这个锁, 包括锁的状态.
     * 方括号中的状态包括 {@code "Write locks ="}紧跟重入持有的写锁的数量
     * 以及{@code "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 + "]";
    }

    /**
     * 返回指定线程的线程ID,即tid字段的值. 我们必须直接访问tid,而不是通过Thread.getId()方法.
     * 因为getId()不是final的,已经知道它可能会被覆写,不再维持唯一映射关系.
     */
    static final long getThreadId(Thread thread) {
        return UNSAFE.getLongVolatile(thread, TID_OFFSET);
    }

    // Unsafe机制
    private static final sun.misc.Unsafe UNSAFE;
    private static final long TID_OFFSET;
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            TID_OFFSET = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("tid"));
        } catch (Throwable e) {
            throw new Error(e);
        }
    }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值