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

            }

  • 相关阅读:
    SpringBoot处理跨域的四种方式
    centos部署nextcloud
    nginx反向代理时配置访问密码
    java对redis的基本操作
    springboot使用redis
    Linux安装redis
    centos安装php7.2环境 (亲测可用)
    linux下后台启动springboot项目
    全局加token
    web移动端浮层滚动阻止window窗体滚动JS/CSS处理
  • 原文地址:https://www.cnblogs.com/beppezhang/p/11214693.html
Copyright © 2020-2023  润新知