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;