ReentrantReadWriteLock实现原理

文章详细阐述了ReentrantReadWriteLock的读锁和写锁在加锁与解锁时的内部逻辑,包括使用CAS操作更新状态,处理锁重入,以及在公平与非公平策略下的不同行为。读锁的获取在没有写锁的情况下,会尝试通过CAS增加共享计数,而解锁时减少计数。写锁涉及到独占锁的概念,加锁时需确保无读写锁存在,释放时将状态置为0。
摘要由CSDN通过智能技术生成

读锁加锁逻辑

protected final int tryAcquireShared(int unused) {
            /*
             * Walkthrough:
             * 1. If write lock held by another thread, fail.
             * 2. Otherwise, this thread is eligible for
             *    lock wrt state, so ask if it should block
             *    because of queue policy. If not, try
             *    to grant by CASing state and updating count.
             *    Note that step does not check for reentrant
             *    acquires, which is postponed to full version
             *    to avoid having to check hold count in
             *    the more typical non-reentrant case.
             * 3. If step 2 fails either because thread
             *    apparently not eligible or CAS fails or count
             *    saturated, chain to version with full retry loop.
             */
            Thread current = Thread.currentThread();
            int c = getState();
            //获取锁的线程如果是写锁,并且非当前线程;则入队
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            int r = sharedCount(c);
            //readerShouldBlock
            //公平实现:如果当前线程是除哨兵节点外的头结点,并且获取锁的线程没有达到阈值,然后CAS获取锁成功
            //非公平实现:如果队列为空,或者头结点为空,获取非共享状态则走以下逻辑
            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);
        }

读锁解锁逻辑

	protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            //当前获取锁的线程只有一个
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                //判断是否有锁重入
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--;
            } else { //对当前线程释放锁
                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                if (count <= 1) {
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                --rh.count;
            }
            //释放锁逻辑
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT;
                if (compareAndSetState(c, nextc))
                    // Releasing the read lock has no effect on readers,
                    // but it may allow waiting writers to proceed if
                    // both read and write locks are now free.
                    return nextc == 0;
            }
        }

写锁解锁逻辑

	protected final boolean tryAcquire(int acquires) {
            /*
             * Walkthrough:
             * 1. If read count nonzero or write count nonzero
             *    and owner is a different thread, fail.
             * 2. If count would saturate, fail. (This can only
             *    happen if count is already nonzero.)
             * 3. Otherwise, this thread is eligible for lock if
             *    it is either a reentrant acquire or
             *    queue policy allows it. If so, update state
             *    and set owner.
             */
            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)---代表存在读锁
                //如果当前存在读锁,或者写锁被其他线程获取
                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;
            }
            //如果是非公平锁则直接会尝试CAS加锁
            //如果是公平锁则判断是否是非哨兵节点外的头结点,如果不是则返回false;然后入队,如果是则CAS成功跳过
            //c==0写锁未被任何线程获取,当前线程是否阻塞或者cas尝试获取锁
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

写锁释放锁逻辑

	protected final boolean tryRelease(int releases) {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
                //设置写锁状态为0
            int nextc = getState() - releases;
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
            //释放锁
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值