ReentrantReadWriteLock 源码分析

ReentrantReadWriteLock  源码分析:

1:数据结构:

成员变量:

private final ReentrantReadWriteLock.ReadLock readerLock; //读取锁

private final ReentrantReadWriteLock.WriteLock writerLock; //写入锁

final Sync sync;    //Sync 对象,继承AQS对象

2:构造函数:

public ReentrantReadWriteLock() {

        this(false); 

}

public ReentrantReadWriteLock(boolean fair) {   //默认 fair= false

        sync = fair ? new FairSync() : new NonfairSync();  //默认创建一个 NonfairSync

        readerLock = new ReadLock(this);     //创建读取锁

        writerLock = new WriteLock(this);     //创建写入锁

}

3:接下来分析ReadLock 读取锁;

  1):成员变量:

private final Sync sync;   // ReadLock 内部维护的Sync对象,和ReentrantReadWriteLock中维护的Sync对象一致;

  2):构造方法:

  protected ReadLock(ReentrantReadWriteLock lock) {

            sync = lock.sync;   //将ReentrantReadWriteLock 构造函数中创建的Sync对象赋给ReadLock 中的Sync属性

        }

4:下面分析ReadLock中的lock方法;

public void lock() {

            sync.acquireShared(1);

        }

acquireShared方法如下:

public final void acquireShared(int arg) {  // arg=1

        if (tryAcquireShared(arg) < 0)

            doAcquireShared(arg);

    }

下面依次分析 tryAcquireShared  doAcquireShared这两个方法:

1): tryAcquireShared    方法:

  protected final int tryAcquireShared(int unused) {  // unused=1

            Thread current = Thread.currentThread();  //当前线程

            int c = getState();          //锁被持有的次数

            if (exclusiveCount(c) != 0 &&

                getExclusiveOwnerThread() != current)  //若为互斥锁 且持有锁的线程不是当前线程则返回-1;

                return -1;

            int r = sharedCount(c);  /获取锁的共享次数

            if (!readerShouldBlock() &&

                r < MAX_COUNT && //锁不需要阻塞等待,共享次数小于最大值,共享次数+1

                compareAndSetState(c, c + SHARED_UNIT)) {

               if (r == 0) {  //第一次获取读取锁 则返回1 获取成功

                    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);  //当队列中首个节点是独占锁时会进入这个逻辑  这里就不分析了

        }

posted @ 2019-07-19 17:38  beppezhang  阅读(320)  评论(0编辑  收藏  举报