ReentrantReadWriteLock.Sync::tryReleaseShared 源码笔记

static final class ThreadLocalHoldCounter
    extends ThreadLocal<HoldCounter> {
    public HoldCounter initialValue() {
        return new HoldCounter();
    }
}
private transient ThreadLocalHoldCounter readHolds;
private transient HoldCounter cachedHoldCounter;

private transient Thread firstReader;
private transient int firstReaderHoldCount;

static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

// 释放写锁
@ReservedStackAccess
protected final boolean tryReleaseShared(int unused) {
    Thread current = Thread.currentThread();
    // 如果当前线程是第一个reader
    // 根据情况修改firstReader和firstReaderHoldCount的值
    // firstReader和firstReaderCount的设置推测是处于程序执行效率的考虑,当只有一个读线程时会非常快速且省内存
    if (firstReader == current) {
        // assert firstReaderHoldCount > 0;
        if (firstReaderHoldCount == 1)
            firstReader = null;
        else
            firstReaderHoldCount--;
    } else { // 当前线程不是第一个reader,此时借助ThreadLocal<HoldCounter>类型的变量rh获取并更新当前线程的写锁重入次数
        // cachedHoldCounter的设置也是出于性能考虑
        HoldCounter rh = cachedHoldCounter;
        if (rh == null ||
            rh.tid != LockSupport.getThreadId(current))
            rh = readHolds.get();
        int count = rh.count;
        if (count <= 1) {
            readHolds.remove();
            if (count <= 0)
                throw unmatchedUnlockException();
        }
        --rh.count;
    }
    // for循环里利用cas更新了state的值,并返回一个布尔类型的值。true代表所有读锁释放完毕,此时写线程可以尝试获取写锁
    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;
    }
}

 

posted @ 2021-05-18 14:05  榆木脑袋0v0  阅读(169)  评论(0)    收藏  举报