美文网首页
ReentrantReadWriteLock源码解析(1)try

ReentrantReadWriteLock源码解析(1)try

作者: 三斤牛肉 | 来源:发表于2021-01-28 15:00 被阅读0次

    读写锁概念:
    写锁排他,读锁共享。

    tryReadLock:

    static final int SHARED_SHIFT   = 16;
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
    
    /** Returns the number of shared holds represented in count  */
    //state的高16位表示读锁
    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
    /** Returns the number of exclusive holds represented in count  */
    //state的低16位表示写锁
    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
    
    final boolean tryReadLock() {
                Thread current = Thread.currentThread();
                for (;;) {
                    int c = getState();
                    if (exclusiveCount(c) != 0 &&//如果有写锁占了,且该写锁不是当前线程,表示不能获取到读锁
                        getExclusiveOwnerThread() != current)
                        return false;
                    int r = sharedCount(c); //读锁计数器
                    if (r == MAX_COUNT)
                        throw new Error("Maximum lock count exceeded");
                    if (compareAndSetState(c, c + SHARED_UNIT)) {//SHARED_UNIT表示1移到高位后位置
                        if (r == 0) {
                            firstReader = current;//放第一个读锁的缓存
                            firstReaderHoldCount = 1;//放第一个读锁的缓存
                        } else if (firstReader == current) {
                            firstReaderHoldCount++; //读锁重入
                        } else {
                            HoldCounter rh = cachedHoldCounter;
                            //if有两种情况:
                            //1)第一次进来
                            //2)缓存的HoldCounter不是当前线程的HoldCounter
                            //则将缓存改为当前线程的Counter
                            //这里理解就是一个缓存操作,提高执行效率
                            if (rh == null || rh.tid != getThreadId(current))
                                cachedHoldCounter = rh = readHolds.get();
                            else if (rh.count == 0)
                                readHolds.set(rh);
                            rh.count++;//增加当前线程的计数器
                        }
                        return true;
                    }
                }
            }
    

    上面可以看到除了和写锁互斥以外,读锁之间并不互斥。所以除了开始判断有没有写锁,之后一路顺畅。

    final boolean tryWriteLock() {
                Thread current = Thread.currentThread();
                int c = getState();
                if (c != 0) {
                    int w = exclusiveCount(c);//获得写锁计数器
                    if (w == 0 || current != getExclusiveOwnerThread())//如果写锁计数器为0或者不是当前线程,注意前面的if(c!=0)判断,说明有锁,但不是写锁(是读锁)
                        return false;
                    if (w == MAX_COUNT)
                        throw new Error("Maximum lock count exceeded");
                }
                //走到这里的情况只可能是c==0或者获得锁的线程是当前线程
                if (!compareAndSetState(c, c + 1))
                    return false;
                setExclusiveOwnerThread(current);
                return true;
            }
    

    相关文章

      网友评论

          本文标题:ReentrantReadWriteLock源码解析(1)try

          本文链接:https://www.haomeiwen.com/subject/mamdaktx.html