ReentrantReadWriteLock 源码解析

ReentrantReadWriteLock 源码解析

ReentrantReadWriteLock 类描述

ReadWriteLock 的实现支持与 ReentrantLock 相似的语义。

该类具有以下属性:

获取顺序:

这个类不会对锁访问施加读取器或写入器的优先顺序。但是,它确实支持一个可选的公平策略。

  1. 非公平模式(默认):

    当构造为非公平(默认)时,读写锁的进入顺序是未指定的,受重入约束。持续竞争的非公平锁可能无限期地推迟一个或多个读线程或写线程,但通常比公平锁具有更高的吞吐量。

  2. 公平模式:

    当构造为公平时,线程使用近似到达顺序策略竞争进入。当释放当前保持的锁时,要么为等待时间最长的单个写线程分配写锁,要么为一组等待时间比所有等待写线程都长的读线程分配读锁。

如果有写锁被持有,或者有一个等待的写线程,那么试图获取公平读锁(不可重入)的线程将阻塞。在当前最老的等待写线程获取并释放写锁之前,线程不会获取读锁。当然,如果一个正在等待的写线程放弃了等待,让一个或多个读线程作为队列中等待时间最长的写锁空闲的线程,那么这些读线程将被分配读锁。

可重入:

这个锁允许读取者和写入者以 ReentrantLock 的方式重新获得读锁或写锁。在写线程持有的所有写锁释放之前,不允许使用不可重入读取器。

此外,写程序可以获得读锁,但反之亦然。在其他应用程序中,当对在读锁下执行读操作的方法的调用或回调期间持有写锁时,重入可能很有用。如果一个读取器试图获取写锁,它将永远不会成功。

锁降级:

重入还允许将写锁降级为读锁,方法是先获取写锁,再获取读锁,然后释放写锁。但是,从读锁升级到写锁是不可能的。

锁获取中断:

读锁和写锁都支持在锁获取期间中断。

Condition 支持:

写锁提供了一个实现 Condition 的方法,其行为与 ReentrantLock 实现的 Condition 的方法相同。当然,这个 Condition 只能与写锁一起使用。

读锁不支持 Condition 并且调用 readLock(). newcondition() 时抛出 UnsupportedOperationException。

仪器仪表:

该类支持确定锁是否被持有或竞争的方法。这些方法是为监控系统状态而设计的,而不是为同步控制而设计的。

这个类的序列化与内置锁的行为相同:反序列化的锁处于未锁定状态,无论其序列化时的状态如何。

示例用法:

下面是一个代码草图,展示了如何在更新缓存后执行锁降级(在以非嵌套方式处理多个锁时,异常处理特别棘手):

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();
    }
  }
}

ReentrantReadWriteLocks 可用于改善某些集合在某些情况下的并发性。通常,只有在期望集合很大、由比写入线程更多的读取器线程访问,并且需要开销超过同步开销的操作时才值得。例如,下面是一个使用TreeMap的类,该类被期望是大的和并发访问的。

 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(); }
   }
 }

实现注意事项:

该锁最多支持65535个递归写锁和65535个读锁。如果试图超过这些限制,则会导致锁定方法抛出 Error 。

ReentrantReadWriteLock 源代码

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    
    /**
     * 内部类提供的读锁
     */
    private final ReadLock readerLock;
    /**
     * 内部类提供的写锁
     */
    private final WriteLock writerLock;
    /**
     * 执行所有同步机制
     */
    final Sync sync;

    /**
     * 无参构造(默认非公平锁)
     */
    public ReentrantReadWriteLock() {
        this(false);
    }

    /**
     * 有参构造,创建公平或非公平锁
     */
    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }

    public WriteLock writeLock() {
        return writerLock;
    }

    public ReadLock readLock() {
        return readerLock;
    }

    /**
     * ReentrantReadWriteLock 的同步实现。分为公平版和非公平版。
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 6317671515068378041L;

        /*
         * 锁状态在逻辑上分为两个无符号短路,用一个 int 值(32 位)表示:
         *
         * 低 16 位表示 写锁的保持计数(包括重入)
         * 高 16 位表示 读锁的保持计数(包括重入)
         */

        /**
         * 共享锁的长度
         */
        static final int SHARED_SHIFT = 16;

        /**
         * 共享锁 增量或者减量
         */
        static final int SHARED_UNIT = (1 << SHARED_SHIFT);

        /**
         * 共享持有数的最大值(包含重入)
         */
        static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;

        /**
         * 00000000 00000000 11111111 11111111  独占锁掩码
         */
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        /**
         * 返回共享锁的保持数
         */
        static int sharedCount(int c) {
            return c >>> SHARED_SHIFT;
        }

        /**
         *  返回独占锁的保持数
         */
        static int exclusiveCount(int c) {
            return c & EXCLUSIVE_MASK;
        }

        /**
         * 每线程读取保持计数的计数器。保持为ThreadLocal;缓存在cachedHoldCounter中
         */
        static final class HoldCounter {
            int count = 0;
            // Use id, not reference, to avoid garbage retention
            final long tid = getThreadId(Thread.currentThread());
        }

        /**
         * ThreadLocal子类。为了反序列化机制,最容易显式定义
         */
        static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
            //初始化调用,当ThreadLocalHoldCounter为null,获取时,会执行初始化
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        /**
         * 当前线程持的保持数。 仅在构造函数和readObject中初始化。
         * 每当线程的读取保持计数降至0时,就会删除。
         */
        private transient ThreadLocalHoldCounter readHolds;

        /**
         * 上一个成功获取readLock的线程的保持计数
         * 在通常情况下,下一个释放的线程是最后一个获取的线程,这样就节省了ThreadLocal查找。
         * 这是非易失的,因为它只是用作启发式方法,并且非常适合线程缓存。
         * 
         * 1.可以比它正在缓存读取保持计数的线程活得更长,但通过不保留对线程的引用来避免垃圾保留。
         * 2.通过良性数据竞争访问;依赖于记忆模型的最终场和凭空保证。
         */
        private transient HoldCounter cachedHoldCounter;

        /**
         * firstReader是第一个获得读锁的线程。firstReaderHoldCount 是第一个读取器的保持数。
         *
         * 1.更准确地说,firstReader是最后一个将共享计数从0改为1的唯一线程,并且从那时起没有释放读锁;如果没有这样的线程,则为null。
         * 2.由于tryreleasshared将其设置为null,除非线程终止而没有释放它的读锁,否则不会导致垃圾保留。
         * 3.通过良性数据竞争访问;依赖于内存模型的凭空保证作为参考。
         * 4.这使得对非竞争读锁的读持有的跟踪非常便宜。
         */
        private transient Thread firstReader = null;
        private transient int firstReaderHoldCount;

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

        /*
         * 公平锁和非公平锁的获取和释放使用相同的代码,但它们在队列非空时是否允许转换上有所不同。
         */

        /**
         * 正在尝试获取读锁的线程是否应该阻塞(阻塞返回 true):
         * 公平模式:等待队列中存在线程,则当前应阻塞。
         * 非公平模式:如果明显的第一个排队线程(如果存在)正在以独占模式等待,则当前应阻塞。
         */
        abstract boolean readerShouldBlock();

        /**
         * 正在尝试获取写锁的线程是否应该阻塞(阻塞返回 true):
         * 公平模式:等待队列中存在线程,则当前应阻塞。
         * 非公平模式:不阻塞,返回 false。
         */
        abstract boolean writerShouldBlock();

        /**
         * 释放独占锁
         */
        protected final boolean tryRelease(int releases) {
            // 判断当前线程是否是持有锁的线程
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            //状态值 - 1
            int nextc = getState() - releases;
            // 如果为 0 释放当前锁
            // 非 0 表示重入了多次,state 状态值 -1 即可
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }

        /**
         * 尝试获取独占锁
         */
        protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);
            // c != 0 表示存在锁
            if (c != 0) {
                // c != 0  and w = 0  表示 有读锁
                // current != getExclusiveOwnerThread() 判断当前线程是否持有锁
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                
                //  c != 0  and w != 0 表示有 写锁;
                //  上一步已经判断当前线程,持有锁。准备进行重入
                //  判断是否大于最大重入次数
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 重入
                setState(c + acquires);
                return true;
            }
            //  c == 0 说明当前锁,未被占有
            //  writerShouldBlock 公平锁,返回是否等待队列有等待的线程。如果有等待的线程,则直接返回false;如果没有通过CAS 获取锁,
            //  writerShouldBlock 非公平锁,返回 false,直接通过CAS获取锁
            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;
                // 第一个线程的保持数是 1 设置   firstReader = null
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--; // 第一个线程重入的情况 firstReaderHoldCount--
            } else {
                // 如果是其他线程释放锁时
                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();

                // 如果当前线程的保持计数小于等于 1,则移除当前线程的保持数
                int count = rh.count;
                if (count <= 1) {
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                // 否则 count--
                --rh.count;
            }
            // 设置状态值 - SHARED_UNIT
            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) {
             Thread current = Thread.currentThread();
            int c = getState();
            // 存在写锁 并且 写锁的持有者不是自己  则返回-1
            if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current)
                return -1;

            // 获取当前持有读锁线程的个数
            int r = sharedCount(c);

            // 1.readerShouldBlock() 根据读锁阻塞策略,不阻塞的情况下
            // 2.r < MAX_COUNT  读锁的个数小于最大值
            // 3.CAS 方法设置 读锁数 + 1
            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 != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            // 进入等待队列,或超过最大读锁数量
            return fullTryAcquireShared(current);
        }

        /**
            * 完全尝试获取共享锁(CAS 方式处理未能获取共享锁的线程)
         */
        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();
                // 存在独占锁,独占锁不是当前线程,返回 -1
                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 != 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;
                }
            }
        }

        /**
         * 尝试获取写锁
         */
        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;
        }

        /**
         * 尝试获取读锁
         */
        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");

                //CAS 尝试获取读锁
                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++;
                    }
                    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 == getThreadId(current))
                return rh.count;

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

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         * 从流中重新构造实例(即反序列化)。
         */
        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;

        /**
         * 写线程总是保持 false,不应该阻塞
         */
        final boolean writerShouldBlock() {
            return false; // writers can always 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();
        }
    }

    /**
     * 方法 ReentrantReadWriteLock.readLock() 返回的读锁。
     */
    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        private final Sync sync;

        /**
         * 子类使用的构造函数
         */
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        /**
         * 获取读取锁。
         * 1.如果另一个线程未持有写锁,则获取读锁并立即返回。
         * 2.如果写锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到获取读锁。
         */
        public void lock() {
            sync.acquireShared(1);
        }

        /**
         * 除非当前线程被中断,否则获取读取锁。
         * 1.如果另一个线程未持有写锁,则获取读锁并立即返回。
         * 2.如果写锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下两种情况之一:
         * 读取锁由当前线程获取;或 其他线程中断当前线程。
         * 3.如果当前线程:在进入该方法时设置其中断状态;或在获取读锁时被中断,则抛出 InterruptedException,并清除当前线程的中断状态。
         * 4.在这个实现中,由于该方法是一个显式中断点,因此优先考虑响应中断,而不是正常或可重入获取锁。
         *
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }

        /**
         * 仅当在调用时另一个线程未持有写锁时,才获取读锁。
         * 
         * 1.如果写锁没有被其他线程持有,则获取读锁,并立即返回值 true。即使该锁被设置为使用公平排序策略,如果读锁可用,调用 tryLock() 也会立即获得该读锁,无论当前是否有其他线程在等待该读锁。
         * 这个 barging;行为在某些情况下是有用的,即使它破坏了公平。如果您想遵守此锁的公平设置,请使用几乎等同的 tryLock(long,TimeUnit) tryLock(0,TimeUnit.SECONDS)(它也检测中断)。
         * 2.如果写锁由另一个线程持有,则此方法将立即返回值 false。
         */
        public boolean tryLock() {
            return sync.tryReadLock();
        }

        /**
         * 如果在给定的等待时间内另一个线程未持有写锁,并且当前线程未被中断,则获取读锁。
         *
         * 1.如果另一个线程未持有写锁,则获取读锁,并立即返回值 true。
         * 如果此锁已设置为使用公平排序策略,则如果任何其他线程正在等待该锁,则不会获取可用的锁。这与 tryLock()方法相反。
         * 如果你想要一个定时的 tryLock 允许闯入一个公平锁,可以将定时和非定时的形式结合在一起:
         *   <pre> {@code
         *  if (lock.tryLock() ||
         *      lock.tryLock(timeout, unit)) {
         *    ...
         *  }}</pre>
         *
         * 2.如果写锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下三种情况之一:
         * 读取锁由当前线程获取;或其他一些线程中断当前线程;或指定的等待时间已过。
         *
         * 3.如果获取了读锁,则返回值 true。
         * 4.如果当前线程:在进入该方法时设置其中断状态;或在获取读锁时被中断,则抛出InterruptedException,并清除当前线程的中断状态。
         * 5.如果经过了指定的等待时间,则返回值 false 。如果时间小于或等于零,则该方法根本不会等待。
         * 6.在该实现中,由于该方法是一个显式中断点,因此优先考虑响应中断而不是正常或可重入获取锁,以及报告等待时间的流逝。
         */
        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);
        }

        /**
         * 读锁不支持 Condition
         */
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }

        public String toString() {
            int r = sync.getReadLockCount();
            return super.toString() +
                    "[Read locks = " + r + "]";
        }
    }

    /**
     * 方法 ReentrantReadWriteLock.writeLock() 返回的写锁。
     */
    public static class WriteLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -4992448646407690164L;
        private final Sync sync;

        /**
         * 子类使用的构造函数
         */
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        /**
         * 
         * 获取写锁。
         * 1.如果读锁和写锁都没有被另一个线程持有,则获取写锁,并立即返回,将写锁持有计数设置为1。
         * 2.如果当前线程已经持有写锁,那么保持计数将增加1,方法将立即返回。
         * 3.如果锁由另一个线程持有,则当前线程出于线程调度的目的而被禁用,并且处于休眠状态,直到获取了写锁,此时写锁持有计数被设置为1。
         */
        public void lock() {
            sync.acquire(1);
        }

        /**
         * 除非当前线程被中断,否则获取写锁。
         * 1.如果读锁和写锁都没有被另一个线程持有,则获取写锁,并立即返回,将写锁持有计数设置为1。
         * 2.如果当前线程已经持有该锁,则持有计数将增加1,方法将立即返回。
         * 3.如果锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下两种情况之一:写锁由当前线程获取;或其他线程 中断 当前线程。
         * 4.如果当前线程获取了写锁,则锁保持计数设置为1。
         * 5.如果当前线程:在进入该方法时设置其中断状态;或在获取写锁时被中断,则抛出 InterruptedException,并清除当前线程的中断状态。
         * 6.在这个实现中,由于该方法是一个显式中断点,因此优先考虑响应中断,而不是正常或可重入获取锁。
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }

        /**
         * 仅当在调用时另一个线程未持有写锁时,才获取写锁。
         *
         * 1.如果读锁和写锁都没有被另一个线程持有,则获取写锁,并立即返回值 true,将写锁持有计数设置为1。
         * 即使此锁已设置为使用公平排序策略,调用 tryLock() 也会立即获取可用的锁,无论其他线程当前是否正在等待写锁。
         * 这个 barging 行为在某些情况下是有用的,即使它破坏了公平。
         * 如果您想遵守此锁的公平性设置,请使用几乎等同的 tryLock(long,TimeUnit) tryLock(0,TimeUnit.SECONDS)(它也检测中断)。
         * 2.如果当前线程已经持有此锁,则持有计数将增加1,方法返回 true。
         * 3.如果锁由另一个线程持有,则此方法将立即返回值 false。
         */
        public boolean tryLock() {
            return sync.tryWriteLock();
        }

        /**
         * 如果在给定的等待时间内另一个线程未持有写锁,并且当前线程未被 中断,则获取写锁。
         * 
         * 1.如果读锁和写锁都没有被其他线程持有,则获取写锁,并立即返回值为 true,将写锁保持计数设置为1。
         * 如果此锁已设置为使用公平排序策略,则如果任何其他线程正在等待写锁,则不会获取可用的锁。这与 tryLock() 方法相反。
         * 如果你想要一个定时的 tryLock 允许闯入一个公平锁,可以将定时和非定时的形式结合在一起:
         *  <pre> {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}</pre>
         *
         * 2.如果当前线程已经持有此锁,则持有计数将增加1,方法返回 true。
         * 3.如果锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下三种情况之一:
         * 写锁由当前线程获取;或其他一些线程中断当前线程;或指定的等待时间已过
         * 4.如果获取了写锁,则返回值 true,并将写锁保持计数设置为1。
         * 5.如果当前线程:在进入该方法时设置其中断状态;或在获取写锁时被中断,则抛出 InterruptedException,并清除当前线程的中断状态。
         * 6.如果经过了指定的等待时间,则返回值 false。如果时间小于或等于零,则该方法根本不会等待。
         * 7.在该实现中,由于该方法是一个显式中断点,因此优先考虑响应中断而不是正常或可重入获取锁,以及报告等待时间的流逝。
         */
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }

        /**
         * 尝试释放此锁。
         * 
         * 如果当前线程是此锁的持有者,那么将减少持有者计数。如果保持计数现在为零,则解除锁定。
         * 如果当前线程不是此锁的持有者,则抛出 IllegalMonitorStateException 。
         */
        public void unlock() {
            sync.release(1);
        }

        /**
         * 返回一个用于Lock 实例的 Condition 实例。
         * 当与内置监视器锁一起使用时,返回的 Condition 实例支持与 Object 监视器方法(Object.wait()、Object.notify()和object.notifyAll()相同的用法。
         *
         * 1.如果在调用任何 Condition 方法时未保持此写锁,则会引发 IllegalMonitorStateException。
         * (读锁是独立于写锁而持有的,因此不会被检查或影响。但是,当当前线程也获取了读锁时,调用条件等待方法本质上总是一个错误,因为其他可以解除锁定的线程将无法获取写锁。)
         * 2.当调用条件 Condition.await()方法时,将释放写锁,在它们返回之前,将重新获取写锁,并将锁保持计数恢复到调用该方法时的状态。
         * 3.如果线程在等待时被中断,那么等待将终止,将抛出 InterruptedException,并清除线程的中断状态。
         * 4.等待线程按FIFO顺序发出信号。
         * 5.从等待方法返回的线程重新获取锁的顺序与最初获取锁的线程相同,默认情况下没有指定,但对于公平锁优先于那些等待时间最长的线程。
         */
        public Condition newCondition() {
            return sync.newCondition();
        }

        public String toString() {
            Thread o = sync.getOwner();
            return super.toString() + ((o == null) ?
                    "[Unlocked]" :
                    "[Locked by thread " + o.getName() + "]");
        }

        /**
         * 查询当前线程是否持有此写锁。与 ReentrantReadWriteLock.isWriteLockedByCurrentThread 的效果相同。
         */
        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }

        /**
         * 查询当前线程对此写锁的保留数。线程对每个锁操作都持有一个锁,而锁操作与解锁操作不匹配。效果与ReentrantReadWriteLock.getWriteHoldCount相同。
         */
        public int getHoldCount() {
            return sync.getWriteHoldCount();
        }
    }

    // =============================================   仪表和状态  ========================================
    // Instrumentation and status

    /**
     * 公平锁返回 true
     */
    public final boolean isFair() {
        return sync instanceof FairSync;
    }

    /**
     * 返回当前拥有写锁的线程,没有则返回 null
     */
    protected Thread getOwner() {
        return sync.getOwner();
    }

    /**
     * 获取读锁保持数(当前有多少读线程获取了该锁)
     */
    public int getReadLockCount() {
        return sync.getReadLockCount();
    }

    /**
     * 查询写锁是否由任何线程持有
     */
    public boolean isWriteLocked() {
        return sync.isWriteLocked();
    }

    /**
     * 查询当前线程是否持有写锁。
     */
    public boolean isWriteLockedByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /**
     * 查询当前线程对此锁的可重入写入保持次数
     */
    public int getWriteHoldCount() {
        return sync.getWriteHoldCount();
    }

    /**
     * 查询当前线程对此锁的可重入读取保持数。
     */
    public int getReadHoldCount() {
        return sync.getReadHoldCount();
    }

    /**
     * 返回包含可能正在等待获取写锁的线程的集合
     */
    protected Collection<Thread> getQueuedWriterThreads() {
        return sync.getExclusiveQueuedThreads();
    }

    /**
     * 返回包含可能正在等待获取读取锁的线程的集合。
     */
    protected Collection<Thread> getQueuedReaderThreads() {
        return sync.getSharedQueuedThreads();
    }

    /**
     * 查询是否有线程正在等待获取读或写锁
     */
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    /**
     * 查询给定线程是否正在等待获取读锁或写锁。
     */
    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    /**
     * 返回等待获取读或写锁的线程数的估计值。
     */
    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    /**
     * 返回一个集合,该集合包含可能正在等待获取读锁或写锁的线程。
     */
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    /**
     * 查询是否有线程正在等待与写锁相关联的给定条件。
     */
    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);
    }

    /**
     * 获取等待该条件的队列长度
     */
    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);
    }

    /**
     * 获取等待该条件的线程集合
     */
    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);
    }

    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。我们必须直接访问它,而不是通过Thread.getId()方法访问,因为getId()不是最终的,并且已知被重写的方式不保留唯一映射。
     */
    static final long getThreadId(Thread thread) {
        return UNSAFE.getLongVolatile(thread, TID_OFFSET);
    }

    // Unsafe mechanics
    private static final sun.misc.Unsafe UNSAFE;
    private static final long TID_OFFSET;

    static {
        try {
            // TODO: 注释源码
            // UNSAFE = sun.misc.Unsafe.getUnsafe();

            //TODO:新增   初始化 unsafe  基于反射获取Unsafe实例
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            UNSAFE = (Unsafe) f.get(null);

            Class<?> tk = Thread.class;
            TID_OFFSET = UNSAFE.objectFieldOffset
                    (tk.getDeclaredField("tid"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

posted @ 2023-02-09 20:01  Cool_Yang  阅读(56)  评论(0编辑  收藏  举报