关于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;

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理