ReentrantReadWriteLock分析

ReentrantReadWriteLock分析

依然使用state变量表示锁的获取状态,因为读写锁涉及读锁和写锁,因此用state变量的高16位和低16位作为区分,分别代表读锁的获取次数,以及写锁的重入次数。
在这里插入图片描述

1、写锁加锁过程

  protected final boolean tryAcquire(int acquires) {
     		// 当前获取锁的线程
            Thread current = Thread.currentThread();
            // 获取state的值,0代表没有任何锁
            int c = getState();
            // 获取写锁的值[低16位]
            int w = exclusiveCount(c);
            // 已经有锁了
            if (c != 0) {
                // 非写锁直接返回fasle, 是写锁但是非当前线程也返回false
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                // 加锁
                setState(c + acquires);
                return true;
            }
            // 无锁,直接加锁
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

在这里插入图片描述

1.1 为什么w == 0直接返回fasle

因为c != 0 说明有线程已经获取到了锁,但是 w == 0 说明是读锁被获取,获取读锁的线程可能是当前线程,也可能是其他线程,也有可能是两者都是。

  • 非当前线程:因为读写互斥,因此加锁失败
  • 当前线程:也就是说,当前线程已经拿到了读锁,再来加写锁,考虑这样一种情况,在还未获取写锁成功的时候,有其他线程来获取读锁,因为读读并发,因此其他线程可以拿到读锁,然鹅当前线程再获取写锁,如果不返回false的话,则会造成,读锁和写锁同时被多个线程持有,打破了读写互斥的原则。

2、写锁释放过程

写锁释放过程相对简单,因为写锁是排他锁,因此和独占锁的释放过程是一样的。将写锁的状态值减去1,判断是否为0了,[考虑重入],为0唤醒下一个排队的线程。

3、读锁的加锁过程

 protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            int r = sharedCount(c);
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                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);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值