ReentrantReadWriteLock源码---JDK1.8

/**
* 读写锁:
* 1.读锁使用共享模式,写锁使用独占模式
* 2.写锁独占,所以会阻塞读锁和写锁,读锁共享,所以只会阻塞写锁
* 3.写锁可以降级为读锁,读锁不能升级写锁
*/

看看构造方法:

//默认为非公平模式
    public ReentrantReadWriteLock() {
        this(false);
    }

 public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }

 

看看内部类Sync:

 /**
         * Sync继承自AQS,在ReentrantReadWriteLock这里,state被分为2部分
         * 高16位,用来表示读锁的持有次数,低16位表示写锁的持有次数。
         * int:
         * 1--->              0000 0000 0000 0000 0000 0000 0000 0001
         * SHARED_UNIT--->    0000 0000 0000 0001 0000 0000 0000 0000
         * MAX_COUNT--->      0000 0000 0000 0000 1111 1111 1111 1111
         * EXCLUSIVE_MASK---> 0000 0000 0000 0000 1111 1111 1111 1111
         */
        static final int SHARED_SHIFT = 16;
        //左移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;


 //每个线程持有读锁次数的计数器,在ThreadLocal中管理,
        static final class HoldCounter {
            int count = 0;
            // Use id, not reference, to avoid garbage retention
            final long tid = getThreadId(Thread.currentThread());
        }

 

/**
         * 独占模式请求的过程:
         *      1.如果锁的持有者不是当前线程,且读锁或者写锁持有次数不为0,请求失败。
         *      2.如果锁持有次数超过上限,请求失败。
         *      3.没超过次数,如果当前是一个重入请求,或者队列策略允许,
         *          那么当前线程可以获取锁,更新状态并设置锁所有者。
         */
        protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            //获取写锁持有次数
            int w = exclusiveCount(c);
            if (c != 0) {
                // (Note: if c != 0 and w == 0 then shared count != 0)
                //c !=0,说明锁被持有,如果w=0,说明当前锁是读锁,再检查一下当前线程是不是
                //持有者
                if (w == 0 || current != getExclusiveOwnerThread())
                    //如果不是,获取失败
                    return false;
                //检查写锁持有次数是否超过最大值MAX_COUNT
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                //更新设置重入次数
                setState(c + acquires);
                return true;
            }
            //到这里说明c=0,说明锁没有被持有,
            //如果写锁需要阻塞或者CAS尝试设置状态失败
            if (writerShouldBlock() ||
                    !compareAndSetState(c, c + acquires))
                //请求失败
                return false;
            //到这里说明写锁不需要阻塞或者CAS成功,那么需要设置当前线程为持有者
            setExclusiveOwnerThread(current);
            return true;
        }

 

//独占模式下尝试释放锁
        protected final boolean tryRelease(int releases) {
            //检查是否是独占模式
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            //状态值减去释放值,得到新的状态值
            int nextc = getState() - releases;
            //判断重入次数是否为0
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                //为0,释放锁,
                setExclusiveOwnerThread(null);
            //更新状态值
            setState(nextc);
            return free;
        }

 

 

 /**
         * 共享模式下尝试请求:
         *      1.如果其他线程持有写锁,请求失败。
         *      2.重入次数超过最大值,抛异常
         *      3.再判断当前队列策略是否需要阻塞读请求,
         *          如果不需要,尝试CAS修改状态,如果修改成功,
         *          更新重入次数,请求成功。
         */
        protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            int c = getState();
            //写锁重入次数
            if (exclusiveCount(c) != 0 &&
                    getExclusiveOwnerThread() != current)
                //如果c!=0,说明锁被持有,检查当前线程是不是持有者,不是,请求失败
                return -1;
            //获取写锁重入次数
            int r = sharedCount(c);
            //判断读锁是否需要阻塞,检查锁重入次数,尝试CAS更新状态
            if (!readerShouldBlock() &&
                    r < MAX_COUNT &&
                    compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) {
                    //如果r=0,说明锁没有被持有,当前线程设置为第一个,
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    //如果还是自己抢到锁了,更新重入值
                    firstReaderHoldCount++;
                } else {
                    //获取缓存的HoldCounter
                    HoldCounter rh = cachedHoldCounter;
                    //判断rh,是否有值,如果没有值,且不是当前线程的HoldCounter
                    if (rh == null || rh.tid != getThreadId(current))
                        //从缓存中获取当前线程的HoldCounter
                        cachedHoldCounter = rh = readHolds.get();
                    //
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    //计数增加
                    rh.count++;
                }
                return 1;
            }
            return fullTryAcquireShared(current);
        }

 

static final class NonfairSync extends Sync {
        //非公平模式下,写总是可以插队
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }

        final boolean readerShouldBlock() {
            //如果同步等待队列头部有写请求,那么当前读请求阻塞
            return apparentlyFirstQueuedIsExclusive();
        }
    }

 

//公平模式,读写锁是否需要阻塞,就是检查同步等待队列是否有更早的线程
    static final class FairSync extends Sync {
        //
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }

        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

 

再看看内部类ReadLock:

 //读锁实现
    public static class ReadLock implements Lock, java.io.Serializable {
        private final Sync sync;
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
        //请求读锁
        //如果有其他线程持有写锁,那么阻塞当前线程,直到请求成功
        //如果没有其他线程持有写锁,那么请求成功
        public void lock() {
            sync.acquireShared(1);
        }
        //响应中断,读锁请求
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }
        //如果没有其他线程持有写锁,那么请求读锁成功
        //读锁是共享锁,所以总会立即成功
        //这里会打破公平策略,如果想遵循策略调用tryLock(0,TimeUni
        public boolean tryLock() {
            return sync.tryReadLock();
        }
        //支持超时,中断的读锁请求。
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }
        //读锁释放
        public void unlock() {
            sync.releaseShared(1);
        }
        //读锁不支持条件,
        public Condition newCondition() {
            throw new UnsupportedOperationExc
}

 

内部类WriteLock:

 

//写锁实现 
public static class WriteLock implements Lock, java.io.Serializable {
        private final Sync sync;
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
        //请求写锁。
        //如果锁没有被线程持有,那么请求写锁成功。
        //如果当前线程已经持有了写锁,叠加重入次数
        //如果有其他线程持有当前锁,当前线程阻塞,直到请求锁成功
        public void lock() {
            sync.acquire(1);
        }
        //支持中断锁请求,响应中断
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
        //如果锁没有被线程持有,那么请求写锁成功。
        //这里会打破公平策略,如果想遵循策略调用tryLock(0,TimeUnit.SECONDS)
        //如果当前线程已经持有了写锁,叠加重入次数
        //如果有其他线程持有当前锁,返回失败
        public boolean tryLock() {
            return sync.tryWriteLock();
        }
        //支持超时中断的读锁请求
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
        public void unlock() {
            sync.release(1);
        }
        public Condition newCondition() {
            return sync.newCondition();
        }
        
        public String toString() {
            Thread o = sync.getOwner();
            return super.toString() + ((o == null) ?
                    "[Unlocked]" :
                    "[Locked by thread " + o.getName() + "]");
        }
        
        //检查写锁是否被当前线程持有,写锁是独占锁
        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }
}

 

posted @ 2017-11-08 15:16  emoji的博客  阅读(178)  评论(0编辑  收藏  举报