java进阶-7-D -多线程-Lock专题- ReentrantReadWriteLock

 

java进阶-7-D -多线程-Lock专题- ReentrantReadWriteLock

相比起ReentrantLock ,ReentrantReadWriteLock 更像是将2个ReentrantLock包装到了一起,一个ReentrantLock是独占锁-writeLock,另外一个是共享锁-readLock ,当然这个内部还有一些润滑剂:比如写锁可以降级成读锁,但是读锁无法升级成写锁...

1.ReentrantReadWriteLock 实现了那些接口?

1.主类实现了 ReadWriteLock接口  2.内部类实现了Lock接口 

Lock接口在前面以及介绍过了,这里简单说一下ReadWriteLock :  就2个方法     readLock  ,  writeLock 

 

2.ReentrantReadWriteLock 理解入口    内部类 :Sync 

读写锁时分开实现的,写锁时独占式锁,所以和前一节的ReentrantLock类似;

读锁:共享锁,在AQS中有对应的参数设置;

 

 1. 读锁获取锁一顿解析------->

        protected final int tryAcquireShared(int unused) {

            Thread current = Thread.currentThread();
            int c = getState();
            //要是有写锁占据 且当前线程并不是占据的那个线程,那就返回 -1 失败
            //从这儿我们看出来 在写锁的内部可以获取读锁
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            //要是读锁不应该被block 且 读锁数量还没越界 且 CAS->读锁数量+1 成功 那就
            int r = sharedCount(c);
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                //就 判断读锁数量 -0 当前线程获取到读锁,数量变为1
                     //要是当前线程以及获取读锁 ,数量+1
                     //当前线程要是没有缓存就加一份,要是有了那就 缓存.holdcount +1 表示新线程 
                     //获取读锁
                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);
        }

 3.关于写锁的一顿分析

protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);     // 写锁状态
            if (c != 0) {
                // 写 == 0 并且 c != 0 表示 读 != 0,即有读锁时获取不到写锁
                // 或者 写 != 0 (有写锁)时但是非本线程,不可以重入
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                //能走到这儿说明 现在是写锁占据,并且当前时写锁重入来了

                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                setState(c + acquires);
                return true;
            }
            // writerShouldBlock() 公平锁 判断队列前面是否有等待,非公平锁 返回false
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

 

final int fullTryAcquireShared(Thread current) {
    HoldCounter rh = null;
    for (;;) {
        int c = getState();
        if (exclusiveCount(c) != 0) {
            // 这里对应锁降级,若当前线程已持有写锁,则允许当前线程继续获取读锁,否则直接返回
            if (getExclusiveOwnerThread() != current)
                return -1;
        } else if (readerShouldBlock()) {
            // 如果读线程需要阻塞
            // 当前线程是第一次获取读锁的线程
            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)) {
            // 下面的处理与tryAcquireShared(int)类似
            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;
        }
    }
}

 

我看到一篇博客总结的挺到位的,这里连接一个地址:

https://blog.****.net/qq_38293564/article/details/80533821