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

本文详细解析了ReentrantReadWriteLock的工作原理,包括其如何通过内部的读锁和写锁实现并发控制,以及如何利用状态字段区分读写操作。文章还深入分析了读锁和写锁的获取过程,揭示了其内部实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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

1.ReentrantReadWriteLock 实现了那些接口?

  • 主类实现了 ReadWriteLock接口 
  • 内部类实现了Lock接口 

2.读/写在lock代码标志中怎么记录与区别?

  • 依旧是state 状态字段,记录获取线程锁的数量
  • int类型长度是32位,小16位存储读线程,后16位存储写线程(位运算存储记录状态)

3.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.youkuaiyun.com/qq_38293564/article/details/80533821

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值