乐趣区

关于java:ReentrantReadWriteLock

ReentrantReadWriteLock

外部类 Sync 简介:

后面看过 AQS 咱们都晓得,AQS 中应用一个 int 型变量来示意锁的持有数,然而对于 ReentrantReadWriteLock 来说,它是分读锁和写锁,那么如何示意这两种锁的持有数呢?读写锁中采纳的形式就是将 int 型一分为二,高 16 位,所有线程持有的读锁数,低 16 位用来示意写锁的持有个数;
读锁是一个共享锁,高 16 位示意的是所有线程总的持读锁数,那如何获取以后线程重入读锁数呢?这里天然引入了 ThreadLocal 来保留每个线程重入读锁的计数。

        static final int SHARED_SHIFT   = 16;// 用于计数出高 161 位的偏移值(读锁)static final int SHARED_UNIT    = (1 << SHARED_SHIFT);//65536
        // 最大持锁个数
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1; // 用于计数出 state 的低 16 位的掩码
        // 该办法获取 int 变量高 16 位,即读锁持有计数
        static int sharedCount(int c)    {return c >>> SHARED_SHIFT;}
        // 该办法获取 int 变量低 16 位,即写锁持有计数
        static int exclusiveCount(int c) {return c & EXCLUSIVE_MASK;}
        // HoldCounter 变量用于存储每个线程 id 以及对应的读锁持有计数
        static final class HoldCounter {
            int count = 0;
            // 应用线程 id 而不是线程援用,是为了避免残留
            // 这里可能是思考到强援用,垃圾对象无奈回收,导致内存泄露
            final long tid = getThreadId(Thread.currentThread());
        }

        // 以后线程持有的读锁计数,ThreadLocalHoldCounter 其实就是一个 ThreadLocal<HoldCounter>
        private transient ThreadLocalHoldCounter readHolds;
        // 上面三个变量是用的比拟多的变量,为了进步获取效率,就独自缓存了
        // 保留上个申请读锁线程的 HoldCounter。private transient HoldCounter cachedHoldCounter;
        // 保留第一个获取到读锁的线程
        private transient Thread firstReader = null;
        // 保留第一个获取到读锁的线程持有的读锁计数
        private transient int firstReaderHoldCount;
退出移动版