java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java并发ReentrantReadWriteLock

Java并发编程ReentrantReadWriteLock加读锁流程

作者:bright丶

这篇文章主要介绍了Java并发编程ReentrantReadWriteLock加读锁流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

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);
}

上面是尝试加读锁流程的代码,既然这篇是番外篇,那就不按正常流程一点一点去分析了,着重拿出一部分来分析一下。ReentrantReadWriteLockReentrantLock相比,除了多了读写锁之外,还增加了很多属性,比如firstReaderfirstReaderHoldCountcachedHoldCounter......那我们这篇文章就介绍一下这些新属性的含义以及上面代码中加锁成功后的处理。

属性介绍

static final class HoldCounter {
    int count = 0;
    final long tid = getThreadId(Thread.currentThread());
}

HoldCount类型用来存储线程ID和线程持有的读锁数量

private transient ThreadLocalHoldCounter readHolds;
static final class ThreadLocalHoldCounter
    extends ThreadLocal&lt;HoldCounter&gt; {
    public HoldCounter initialValue() {
        return new HoldCounter();
    }
}

readHolds通过ThreadLocal在线程本地存储了一个HoldCounter对象,表示当前线程持有的读锁重入数量,主要是为了方便在发生重入或者释放锁时,分别计算每个线程持有的读锁数量。

private transient HoldCounter cachedHoldCounter;

cachedHoldCounter存储的是最后一个获取读锁成功的线程持有的读锁数量。但是如果只有一个线程获取读锁,会使用firstReaderfirstReaderHoldCount来记录线程持有读锁数量,只有获取读锁的线程数大于1时才会用cachedHoldCounter存储最后线程持有的读锁数量。

private transient Thread firstReader = null;

第一个获取读锁的线程,确切地说是把读锁数量从0改成1的线程,并且当前还没有释放锁。如果第一个线程释放了锁,就会把firstReader设为null,只有当所有读锁释放之后,下一个获取读锁成功的线程就成为firstReader

private transient int firstReaderHoldCount;

第一个获取读锁的线程持有读锁的数量。

加锁成功处理

int r = sharedCount(c);
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++;
}

这里截取加锁成功之后处理的代码来分析下对这些属性的操作。

以上就是Java并发编程ReentrantReadWriteLock番外的详细内容,更多关于Java并发ReentrantReadWriteLock的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文