ReentrantReadWriteLock源码解析(1)try

2021-01-28  本文已影响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;
        }
上一篇下一篇

猜你喜欢

热点阅读