Java并发编程解析 | 基于JDK源码解析Java领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理 (二)

苍穹之边,浩瀚之挚,眰恦之美; 悟心悟性,善始善终,惟善惟道! —— 朝槿《朝槿兮年说》


写在开头

在并发编程领域,有两大核心问题:一个是互斥,即同一时刻只允许一个线程访问共享资源;另一个是同步,即线程之间如何通信、协作。<br />主要原因是,对于多线程实现实现并发,一直以来,多线程都存在2个问题:

  • 线程之间内存共享,需要通过加锁进行控制,但是加锁会导致性能下降,同时复杂的加锁机制也会增加编程编码难度
  • 过多线程造成线程之间的上下文切换,导致效率低下

因此,在并发编程领域中,一直有一个很重要的设计原则: “ 不要通过内存共享来实现通信,而应该通过通信来实现内存共享。”<br />简单来说,就是尽可能通过消息通信,而不是内存共享来实现进程或者线程之间的同步。

关健术语

<br />本文用到的一些关键词语以及常用术语,主要如下:

  • 并发(Concurrent): 在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。
  • 并行(Parallel): 当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行。
  • 信号量(Semaphore): 是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用,也是作系统用来解决并发中的互斥和同步问题的一种方法。
  • 信号量机制(Semaphores): 用来解决同步/互斥的问题的,它是1965年,荷兰学者 Dijkstra提出了一种卓有成效的实现进程互斥与同步的方法。
  • 管程(Monitor) : 一般是指管理共享变量以及对共享变量的操作过程,让它们支持并发的一种机制。
  • 互斥(Mutual Exclusion):一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。即就是同一时刻只允许一个线程访问共享资源的问题。
  • 同步(Synchronization):两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。即就是线程之间如何通信、协作的问题。
  • 对象池(Object Pool): 指的是一次性创建出 N 个对象,之后所有的线程重复利用这 N 个对象,当然对象在被释放前,也是不允许其他线程使用的, 一般指保存实例对象的容器。

基本概述

在Java领域中,我们可以将锁大致分为基于Java语法层面(关键词)实现的锁和基于JDK层面实现的锁。

在Java领域中, 尤其是在并发编程领域,对于多线程并发执行一直有两大核心问题:同步和互斥。其中:

  • 互斥(Mutual Exclusion):一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。即就是同一时刻只允许一个线程访问共享资源的问题。
  • 同步(Synchronization):两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。即就是线程之间如何通信、协作的问题。

针对对于这两大核心问题,利用管程是能够解决和实现的,因此可以说,管程是并发编程的万能钥匙。<br />虽然,Java在基于语法层面(synchronized 关键字)实现了对管程技术,但是从使用方式和性能上来说,内置锁(synchronized 关键字)的粒度相对过大,不支持超时和中断等问题。<br />为了弥补这些问题,从JDK层面对其“重复造轮子”,在JDK内部对其重新设计和定义,甚至实现了新的特性。<br />在Java领域中,从JDK源码分析来看,基于JDK层面实现的锁大致主要可以分为以下4种方式:

  • 基于Lock接口实现的锁:JDK1.5版本提供的ReentrantLock类
  • 基于ReadWriteLock接口实现的锁:JDK1.5版本提供的ReentrantReadWriteLock类
  • 基于AQS基础同步器实现的锁:JDK1.5版本提供的并发相关的同步器Semaphore,CyclicBarrier以及CountDownLatch等
  • 基于自定义API操作实现的锁:JDK1.8版本中提供的StampedLock类

从阅读源码不难发现,在Java SDK 并发包主要通过AbstractQueuedSynchronizer(AQS)实现多线程同步机制的封装与定义,而通过Lock 和 Condition 两个接口来实现管程,其中 Lock 用于解决互斥问题,Condition 用于解决同步问题。


一.AQS基础同步器基本理论

在Java领域中,同步器是专门为多线程并发设计的同步机制,主要是多线程并发执行时线程之间通过某种共享状态来实现同步,只有当状态满足这种条件时线程才往下执行的一种同步机制。

<br />一个标准的AQS同步器主要有同步状态机制,等待队列,条件队列,独占模式,共享模式等五大核心要素组成。<br />在Java领域中,JDK的JUC(java.util.concurrent.)包中提供了各种并发工具,但是大部分同步工具的实现基于AbstractQueuedSynchronizer类实现,其内部结构主要如下:

  • 同步状态机制(Synchronization Status):主要用于实现锁(Lock)机制,是指同步状态,其要求对于状态的更新必须原子性的
  • 等待队列(Wait Queue):主要用于存放等待线程获取到的锁资源,并且把线程维护到一个Node(节点)里面和维护一个非阻塞的CHL Node FIFO(先进先出)队列,主要是采用自旋锁+CAS操作来保证节点插入和移除的原子性操作。
  • 条件队列(Condition Queue):用于实现锁的条件机制,一般主要是指替换“等待-通知”工作机制,主要是通过ConditionObject对象实现Condition接口提供的方法实现。
  • 独占模式(Exclusive Mode):主要用于实现独占锁,主要是基于静态内部类Node的常量标志EXCLUSIVE来标识该节点是独占模式
  • 共享模式(Shared Mode):主要用于实现共享锁,主要是基于静态内部类Node的常量标志SHARED来标识该节点是共享模式

我们可以得到一个比较通用的并发同步工具基础模型,大致包含如下几个内容,其中:<br />
  • 条件变量(Conditional Variable): 利用线程间共享的变量进行同步的一种工作机制
  • 共享变量((Shared Variable)):一般指对象实体对象的成员变量和属性
  • 阻塞队列(Blocking Queue):共享变量(Shared Variable)及其对共享变量的操作统一封装
  • 等待队列(Wait Queue):每个条件变量都对应有一个等待队列(Wait Queue),内部需要实现入队操作(Enqueue)和出队操作(Dequeue)方法
  • 变量状态描述机(Synchronization Status):描述条件变量和共享变量之间状态变化,又可以称其为同步状态
  • 工作模式(Operation Mode): 线程资源具有排他性,因此定义独占模式和共享模式两种工作模式

综上所述,条件变量和等待队列的作用是解决线程之间的同步问题;共享变量与阻塞队列的作用是解决线程之间的互斥问题。

二. JDK显式锁统一概念模型

在并发编程领域,有两大核心问题:一个是互斥,即同一时刻只允许一个线程访问共享资源;另一个是同步,即线程之间如何通信、协作。

综合Java领域中的并发锁的各种实现与应用分析来看,一把锁或者一种锁,基本上都会包含以下几个方面:

  • 锁的同步器工作机制:主要是考虑共享模式还是独享模式,是否支持超时机制,以及是否支持超时机制?
  • 锁的同步器工作模式:主要是基于AQS基础同步器封装内部同步器,是否考虑公平/非公平模式?
  • 锁的状态变量机制: 主要锁的状态设置,是否共享状态变量?
  • 锁的队列封装定义:主要是指等待队列和条件队列,是否需要条件队列或者等待队列定义?
  • 锁的底层实现操作: 主要是指底层CL锁和CAS操作,是否需要考虑自旋锁或者CAS操作实例对象方法?
  • 锁的组合实现新锁: 主要是基于独占锁和共享锁,是否考虑对应API自定义操作实现?

综上所述,大致可以根据上述这些方向,我们便可以清楚🉐️知道Java领域中各种锁实现的基本理论时和实现思想。


四.ReentrantReadWriteLock(读写锁)的设计与实现

在Java领域中,ReentrantReadWriteLock(读写锁)是针对于Java多线程并发控制中引入一个共享锁定义读操作与独占锁定义读操作等场景共同组合构成一把锁来提高并发,主要是基于内置的AQS基础抽象队列同步器实现的一种并发控制工具类。

<br />通过ReentrantReadWriteLock类能获取读锁和写锁,它的读锁是可以多线程共享的共享锁,而它的写锁是排他锁,在被占时不允许其他线程再抢占操作。

1. 设计思想

<br />一般来说,在一些特殊的场景中,比如对于数据的读和写操作,为提高并发性能,总会引入共享锁和独享锁来共同组成一把锁,通常情况下,我们把这类锁成为读写锁(ReadWriteLock) 。<br />简单来说,就是主要考虑读和写操作,读操作不会修改数据,可以利用多个线程进行读操作,一般采用共享锁实现;而写操作会改变数据本身,只能允许一个线程进行操作,因此采用独享锁实现。<br />读写锁(ReadWriteLock) 最大的一个特点就是在内部维护一对锁,一把读锁(ReadLock) ,一把写锁(WriteLock) 。其中,对于线程持有的情况来说,简单可以总结为“读共享,写独占”。

1.1 读写锁的基本理论

虽然读写锁(ReadWriteLock) 之间是有关系的:同一时刻不允许读锁和写锁同时被抢占,二者之间是互斥的。<br />假设现在有N个线程,主要从T(1),T(2),...,一直到T(N)个线程,在读写锁的操作情况如下,其中:

  • 多读模式(多读共享):T(N) 个线程可以同时把持并获取读锁,假设T(1)线程成功获取并持有读锁,T(2)线程和后续的T(N)个线程依然可以成功获取读锁,即使T(1)线程没有释放持有的读锁。
  • 读写模式(读写互斥):假设T(1)线程成功获取并持有读锁,T(2)线程和后续的T(N)个线程便不能成功获取且持有写锁,除非T(1)线程已经释放持有的读锁。
  • 独写模式(单写独占):假设T(1)线程成功获取并持有写锁,T(2)线程和后续的T(N)个线程便不能成功获取且持有读锁和写锁,只能等待等待T(1)线程释放完持有的写锁,才能继续往下执行。

从一定意义上讲,根据读写锁操作的情况的性质分析,获取读锁和写锁的条件可以大致总结为:

  • 获取读锁的条件:当前任何线程没有成功获取且已经持有写锁的情况,才可能获取并持有读锁。
  • 获取写锁的条件:当前任何线程没有成功获取且已经持有写锁和读锁的情况,才可能获取并持有写锁。

但是在某些情况下,可能存在某个线程已经获取并持有读锁,希望能够获取写锁,并且在已经释放读锁时,通常情况下我们称之为读写锁的升级。<br />当然,有升级就会有降级,与之对应的就是读写锁的降级,主要描述的是某个线程已经获取并持有写锁,希望能够获取读锁,并且已经释放写锁。<br />一般来说,对于读写锁的升级与降级,我们一般需要注意的以下两个问题,其中:

  • 读写锁的升级:指的是读锁升级为写锁的情况,需要满足某个线程必须是唯一拥有读锁的线程的条件,否则无法升级。
  • 读写锁的降级:指的是写锁降级为读锁的情况,没有什么条件限制,写锁是独占锁,其持有线程是唯一的且不会存在读锁持有线程的情况,可以直接平滑升级读锁。

1.2 读写锁的实现思想

ReentrantReadWriteLock最早是在JDK1.5版本中提供的,从设计思想上来看,主要包括同步器的工作模式,读锁和写锁等3个核心要素。其中:

  • 实现ReadWriteLock接口 :主要基于ReadWriteLock接口API实现对应方法,主要是实现writeLock()方法和readLock() 方法,其中writeLock()方法表示获取写锁,readLock() 方法表示获取读锁。
  • 同步器的工作模式:基于AQS基础抽象队列同步器封装内置实现一个静态的内置同步器抽象类,然后基于这个抽象类分别实现了公平同步器和非公平同步器,用来指定和描述同步器工作模式是公平模式还是非公平模式。
  • 公平/非公平模式:主要描述的是多个线程在同时获取锁时是否按照先到先得的顺序获取锁,如果是则为公平模式,否则为非公平模式。
  • 内置两个静态公有内部类:定义了读锁和写锁静态公有内部类,并且都支持公平/非公平模式,本质都是基于AQS基础抽象队列同步器实现。
  • 维护共享状态变量: 主要是基于一个AQS基础抽象队列同步器来实现读锁和写锁,要求共用一个共享状态变量。

2. 基本实现

在ReentrantReadWriteLock类在JDK1.8版本中,对于ReentrantReadWriteLock的基本实现如下:

public class ReentrantReadWriteLock
    implements ReadWriteLock, java.io.Serializable {

        private static final long serialVersionUID = -6992448646407690164L;

        /** ReentrantReadWriteLock锁-内部ReadLock类 */
        private final ReentrantReadWriteLock.ReadLock readerLock;

        /** ReentrantReadWriteLock锁-内部WriteLock类 */
        private final ReentrantReadWriteLock.WriteLock writerLock;

        /** ReentrantReadWriteLock锁-内部同步器 */
        final Sync sync; 

        /** ReentrantReadWriteLock锁-基于AQS封装内部同步器 */
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = 6317671515068378041L;

            /** ReentrantReadWriteLock锁-共用状态变量封装-begin*/

            /** ReentrantReadWriteLock锁-共用状态变量封装-共享状态移动位数16 */
            static final int SHARED_SHIFT   = 16;

            /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的状态大小*/
            static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

            /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的最大次数*/
            static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

            /** ReentrantReadWriteLock锁-共用状态变量封装-写锁的掩码*/
            static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

            /** ReentrantReadWriteLock锁-共用状态变量封装-本地存储读锁次数*/
            private transient ThreadLocalHoldCounter readHolds;

            /** ReentrantReadWriteLock锁-共用状态变量封装-读锁的状态码值*/
            private transient HoldCounter cachedHoldCounter;

            /** ReentrantReadWriteLock锁-共用状态变量封装-线程变量*/
            private transient Thread firstReader = null;

            /** ReentrantReadWriteLock锁-共用状态变量封装-首次读锁次数*/
            private transient int firstReaderHoldCount;

            /** ReentrantReadWriteLock锁-共用状态变量封装-end*/

            Sync() {
                readHolds = new ThreadLocalHoldCounter();
                setState(getState()); // ensures visibility of readHolds
            }

            /** ReentrantReadWriteLock锁-读锁标记*/
            abstract boolean readerShouldBlock();

            /** ReentrantReadWriteLock锁-读锁标记*/
            abstract boolean writerShouldBlock();

            //... 其他代码
        }



        /** ReentrantReadWriteLock锁-无参数构造(默认非公平模式) */
        public ReentrantReadWriteLock() {
            this(false);
        }

        /** ReentrantReadWriteLock锁-有参数构造(可选公平/非公平模式) */
        public ReentrantReadWriteLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
            readerLock = new ReadLock(this);
            writerLock = new WriteLock(this);
        }

        /** ReentrantReadWriteLock锁-获取写锁 */
        public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }      
        /** ReentrantReadWriteLock锁-获取读锁 */
        public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }


        /** ReentrantReadWriteLock锁-实例化Unsafe支持 */
        private static final sun.misc.Unsafe UNSAFE;

        /** ReentrantReadWriteLock锁-线程偏移量 */
        private static final long TID_OFFSET;

        /** ReentrantReadWriteLock锁-获取线程变量 */
        static final long getThreadId(Thread thread) {
            return UNSAFE.getLongVolatile(thread, TID_OFFSET);
        }

        /** ReentrantReadWriteLock锁-反射机制实例化Unsafe */
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> tk = Thread.class;
                TID_OFFSET = UNSAFE.objectFieldOffset
                    (tk.getDeclaredField("tid"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
  • 内部同步器:基于AQS基础同步器封装和定义了一个静态内部Sync抽象类
  • 同步器工作模式:提供了 2个构造方法,其中无参数构造方法表示的是默认的工作模式,有参数构造方法主要依据参数来实现指定的工作模式
  • 公平/非公平模式:主要是基于Sync抽象类封装NonfairSync非公平同步器和封装NonfairSync非公平同步器来实现。
  • 内置两个内部类:主要是实现了ReadLock类和WriteLock类,其中ReadLock类对应着读锁,WriteLock类对应着写锁。

2.1 基于AQS同步器封装静态内部Sync抽象类

/** ReentrantReadWriteLock锁-基于AQS封装内部同步器 */
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 6317671515068378041L;

    /** ReentrantReadWriteLock锁-共用状态变量封装-begin */

    /** ReentrantReadWriteLock锁-共用状态变量封装-共享状态移动位数16 */
    static final int SHARED_SHIFT   = 16;

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的状态大小*/
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的最大次数*/
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock锁-共用状态变量封装-写锁的掩码*/
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock锁-共用状态变量封装-本地存储读锁次数*/
    private transient ThreadLocalHoldCounter readHolds;

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁的状态码值*/
    private transient HoldCounter cachedHoldCounter;

    /** ReentrantReadWriteLock锁-共用状态变量封装-线程变量*/
    private transient Thread firstReader = null;

    /** ReentrantReadWriteLock锁-共用状态变量封装-首次读锁次数*/
    private transient int firstReaderHoldCount;

    /** ReentrantReadWriteLock锁-共用状态变量封装-end*/

    Sync() {
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }


    /** ReentrantReadWriteLock锁-读锁标记*/
    abstract boolean readerShouldBlock();

    /** ReentrantReadWriteLock锁-读锁标记*/
    abstract boolean writerShouldBlock();

    /** ReentrantReadWriteLock锁-独占模式获取读锁*/
    protected final boolean tryRelease(int releases) {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int nextc = getState() - releases;
        boolean free = exclusiveCount(nextc) == 0;
        if (free)
            setExclusiveOwnerThread(null);
        setState(nextc);
        return free;
    }

    /** ReentrantReadWriteLock锁-独占模式释放锁*/
    protected final boolean tryAcquire(int acquires) {

        Thread current = Thread.currentThread();
        int c = getState();
        int w = exclusiveCount(c);
        if (c != 0) {
            // (Note: if c != 0 and w == 0 then shared count != 0)
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w + exclusiveCount(acquires) > MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            // Reentrant acquire
            setState(c + acquires);
            return true;
        }
        if (writerShouldBlock() ||
            !compareAndSetState(c, c + acquires))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    /** ReentrantReadWriteLock锁-共享模式释放锁*/
    protected final boolean tryReleaseShared(int unused) {
        Thread current = Thread.currentThread();
        if (firstReader == current) {
            // assert firstReaderHoldCount > 0;
            if (firstReaderHoldCount == 1)
                firstReader = null;
            else
                firstReaderHoldCount--;
        } else {
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != getThreadId(current))
                rh = readHolds.get();
            int count = rh.count;
            if (count <= 1) {
                readHolds.remove();
                if (count <= 0)
                    throw unmatchedUnlockException();
            }
            --rh.count;
        }
        for (;;) {
            int c = getState();
            int nextc = c - SHARED_UNIT;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
        }
    }

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

    /** ReentrantReadWriteLock锁-共享模式获取锁*/
    final int fullTryAcquireShared(Thread current) {

        HoldCounter rh = null;
        for (;;) {
            int c = getState();
            if (exclusiveCount(c) != 0) {
                if (getExclusiveOwnerThread() != current)
                    return -1;
                // else we hold the exclusive lock; blocking here
                // would cause deadlock.
            } else if (readerShouldBlock()) {
                // Make sure we're not acquiring read lock reentrantly
                if (firstReader == current) {
                    // assert firstReaderHoldCount > 0;
                } else {
                    if (rh == null) {
                        rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current)) {
                            rh = readHolds.get();
                            if (rh.count == 0)
                                readHolds.remove();
                        }
                    }
                    if (rh.count == 0)
                        return -1;
                }
            }
            if (sharedCount(c) == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, c + SHARED_UNIT)) {
                if (sharedCount(c) == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    if (rh == null)
                        rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                    cachedHoldCounter = rh; // cache for release
                }
                return 1;
            }
        }
    }

    /** ReentrantReadWriteLock锁-判断是否独占模式*/
    protected final boolean isHeldExclusively() {
        return getExclusiveOwnerThread() == Thread.currentThread();
    }

    // Methods relayed to outer class

    /** ReentrantReadWriteLock锁-定义条件变量*/
    final ConditionObject newCondition() {
        return new ConditionObject();
    }

    /** ReentrantReadWriteLock锁-获取当前锁的持有者*/
    final Thread getOwner() {
        // Must read state before owner to ensure memory consistency
        return ((exclusiveCount(getState()) == 0) ?
                null :
                getExclusiveOwnerThread());
    }

    /** ReentrantReadWriteLock锁-获取读锁次数统计*/
    final int getReadLockCount() {
        return sharedCount(getState());
    }

    /** ReentrantReadWriteLock锁-判断是否是写锁*/
    final boolean isWriteLocked() {
        return exclusiveCount(getState()) != 0;
    }

    /** ReentrantReadWriteLock锁-获取写锁持有次数统计*/
    final int getWriteHoldCount() {
        return isHeldExclusively() ? exclusiveCount(getState()) : 0;
    }

    /** ReentrantReadWriteLock锁-获取读锁次持有数统计*/
    final int getReadHoldCount() {
        if (getReadLockCount() == 0)
            return 0;

        Thread current = Thread.currentThread();
        if (firstReader == current)
            return firstReaderHoldCount;

        HoldCounter rh = cachedHoldCounter;
        if (rh != null && rh.tid == getThreadId(current))
            return rh.count;

        int count = readHolds.get().count;
        if (count == 0) readHolds.remove();
        return count;
    }

    /** ReentrantReadWriteLock锁-获取读锁*/
    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)) {
                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 true;
            }
        }
    }

    /** ReentrantReadWriteLock锁-获取写锁*/
    final boolean tryWriteLock() {
        Thread current = Thread.currentThread();
        int c = getState();
        if (c != 0) {
            int w = exclusiveCount(c);
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
        }
        if (!compareAndSetState(c, c + 1))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

    /** ReentrantReadWriteLock锁-流处理*/
    private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        readHolds = new ThreadLocalHoldCounter();
        setState(0); // reset to unlocked state
    }

    /** ReentrantReadWriteLock锁-获取状态*/
    final int getCount() { return getState(); }

}
  • 实现方式: 主要是基于AQS基础同步器来实现,其中封装抽象了readerShouldBlock()方法和writerShouldBlock()方法,用于标记当前请求的线程是获取什么类型的锁。其中:
    • readerShouldBlock()方法:依据标记返回的是true,标记线程获取的是ReadLock锁
    • writerShouldBlock()方法:依据标记返回的是true,标记线程获取的是WriteLock锁
  • 维护共用状态变量: 对于共享状态变量的实现,主要是在内部的同步器中Sync类中定义HoldCounter类和ThreadLocalHoldCounter类实现的,其中定义了一堆常量,统计读写锁状态值的sharedCount()方法和exclusiveCount()方法。
  • 读写锁的主要方法: 主要是提供了tryReadLock()方法和tryWriteLock()方法,其中:
    • tryReadLock()方法:获取读锁方法,核心处理是自旋+compareAndSetState()方法来处理
    • tryWriteLock()方法:获取写锁方法,核心处理是通过compareAndSetState()方法来处理
  • 读写锁的获取方式:基于AQS基础同步器来实现对于共享模式和独享模式两种情况,都提供了对应的方法。其中:
    • tryAcquire()方法:独享模式获取锁方法,这里主要针对WriteLock锁,核心处理是通过AQS基础同步器中compareAndSetState()方法来处理,实现状态变量的操作
    • tryAcquireShared() 方法:共享模式获取锁方法,这里主要对应ReadLock锁,核心处理是通过AQS基础同步器中compareAndSetState()方法来处理,实现状态变量的操作
  • 读写锁的释放方式:基于AQS基础同步器来实现对于共享模式和独享模式两种情况,都提供了对应的方法。其中:
    • tryRelease(int releases) 方法:独享模式释放锁方法
    • tryReleaseShared(int unused) 方法:共享模式释放锁方法,核心处理是自旋+compareAndSetState()方法来处理
  • 其他方法:主要还提供了一些比较常规的方法,其中:
    • getCount() 方法:主要是基于AQS基础同步器来获取状态变量
    • getOwner()方法:主要是用于获取当前锁的持有者,一般是线程对象,根据exclusiveCount(getState()) == 0来判断,条件成立就默认为null; 否则,通过AQS基础同步器中的getExclusiveOwnerThread()方法来获取。
    • getReadLockCount() 方法:用于获取某个线程对于ReadLock锁的数量,主要是统计次数
    • isWriteLocked() 方法:用于判断线程是否已经获取并持有WriteLock锁
    • getWriteHoldCount()方法:用于获取线程对于WriteLock锁的持有情况,主要是统计次数
    • getReadHoldCount() 方法:用于获取线程对于WriteLock锁的持有情况,主要是统计次数
    • isHeldExclusively() 方法:用于判断是否独占模式
    • unmatchedUnlockException()方法:封装一个异常处理信息,主要是指定IllegalMonitorStateException

2.2 基于Sync抽象类封装共享状态变量

/** ReentrantReadWriteLock锁-基于AQS封装内部同步器 */
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 6317671515068378041L;

    /** ReentrantReadWriteLock锁-共用状态变量封装-begin*/
    
    /** ReentrantReadWriteLock锁-共用状态变量封装-共享状态移动位数16 */
    static final int SHARED_SHIFT   = 16;

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的状态大小*/
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁每次加锁的最大次数*/
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock锁-共用状态变量封装-写锁的掩码*/
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

    /** ReentrantReadWriteLock锁-共用状态变量封装-本地存储读锁次数*/
    private transient ThreadLocalHoldCounter readHolds;

    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁的状态码值*/
    private transient HoldCounter cachedHoldCounter;

    /** ReentrantReadWriteLock锁-共用状态变量封装-线程变量*/
    private transient Thread firstReader = null;

    /** ReentrantReadWriteLock锁-共用状态变量封装-首次读锁次数*/
    private transient int firstReaderHoldCount;

    /** ReentrantReadWriteLock锁-共用状态变量封装-end*/
    
    /** ReentrantReadWriteLock锁-共用状态变量封装-构造方法*/
    Sync() {
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }


    /** ReentrantReadWriteLock锁-共用状态变量封装-读锁的状态码值*/
    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }

    /** ReentrantReadWriteLock锁-共用状态变量封装-写锁的状态码值*/
    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

    /** ReentrantReadWriteLock锁-共用状态变量-统计计数器 */
    static final class HoldCounter {
        int count = 0;
        // Use id, not reference, to avoid garbage retention
        final long tid = getThreadId(Thread.currentThread());
    }

    /** ReentrantReadWriteLock锁-共用状态变量-本地存储统计副本 */
    static final class ThreadLocalHoldCounter
        extends ThreadLocal<HoldCounter> {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }
    //... 其他代码

}
  • 实现方式: 主要是在内部的同步器中Sync类中定义HoldCounter类和ThreadLocalHoldCounter类实现的。其中:
    • HoldCounter类:主要是定义了一个计数器count和一个线程编号tid变量,其中计数器count默认值为0,而线程编号tid通过getThreadId(Thread.currentThread())方法来获取。
    • ThreadLocalHoldCounter类:基于ThreadLocal和HoldCounter来提供了initialValue()方法,主要是实例话化HoldCounter类。
  • 共用状态常量:主要是在内部的同步器中Sync类中定义了相关常量,其中:
    • SHARED_SHIFT: 主要用于标记位移的位数,默认采用 整型16位
    • SHARED_UNIT:表示读锁加锁操作时每次对应的状态值大小,将1左移动16位正好对应高16位的1.
    • MAX_COUNT:表示读锁能执行加锁操作的最大次数,一般为16个二进制的1
    • EXCLUSIVE_MASK:写锁的掩码,一般为16个二进制的1
  • 主要方法:主要提供了统计读写锁状态值的sharedCount()方法和exclusiveCount()方法,其中:
    • sharedCount()方法:获取读锁的状态码值,根据目标参数(targetParam)左移16位即可得到
    • exclusiveCount()方法:获取写锁的状态码值,根据目标参数(targetParam)同写锁的掩码做逻辑与(&)运算便可得到。

一般来说,AQS基础同步器的共享状态变量是整型的32位,要基于一个AQS基础同步器实现读写锁的共享一个共享变量。<br />其中,最公平的方式设计方式就是读锁与写锁各自占用16位,就意味着读锁占用的是高16位,写锁占用的是低16位的。

但是,在获取读写锁的状态值的时候,还会涉及一些额外的计算,这样的设计方式可能会需要用到位移和逻辑与操作等。

2.3 基于Sync抽象类封装FairSync公平同步器

/** ReentrantReadWriteLock锁-基于Sync抽象类封装FairSync公平同步器 */
static final class FairSync extends Sync {

    private static final long serialVersionUID = -2274990926593161451L;

    /** ReentrantReadWriteLock锁- 实现writerShouldBlock方法*/
    final boolean writerShouldBlock() {
        return hasQueuedPredecessors();
    }

    /** ReentrantReadWriteLock锁- 实现readerShouldBlock方法*/
    final boolean readerShouldBlock() {
        return hasQueuedPredecessors();
    }
}
  • 实现方式:基于Sync抽象类封装FairSync公平同步器,表示支持公平模式
  • 主要方法:主要实现实现writerShouldBlock()方法和readerShouldBlock()方法,其中:
    • writerShouldBlock()方法:通过hasQueuedPredecessors()实现
    • readerShouldBlock()方法:通过apparentlyFirstQueuedIsExclusive()实现

2.4 基于Sync抽象类封装NonfairSync非公平同步器


/** ReentrantReadWriteLock锁-基于Sync抽象类封装FairSync公平同步器 */
static final class NonfairSync extends Sync {
    
    private static final long serialVersionUID = -8159625535654395037L;
    
    /** ReentrantReadWriteLock锁- 实现writerShouldBlock方法*/
    final boolean writerShouldBlock() {
        return false; // writers can always barge
    }

    /** ReentrantReadWriteLock锁- 实现readerShouldBlock方法*/
    final boolean readerShouldBlock() {
        return apparentlyFirstQueuedIsExclusive();
    }
}

  • 实现方式:基于Sync抽象类封装NonfairSync非公平同步器,表示支持非公平模式
  • 主要方法:主要实现实现writerShouldBlock()方法和readerShouldBlock()方法,其中:
    • writerShouldBlock()方法:默认返回false
    • readerShouldBlock()方法:通过apparentlyFirstQueuedIsExclusive()实现

2.5 基于Lock接口实现ReadLock读锁内部类

/** ReentrantReadWriteLock锁-基于Lock接口实现ReadLock读锁内部类*/
public static class ReadLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = -5992448646407690164L;

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-同步器 */
    private final Sync sync;

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-内部构造方法*/
    protected ReadLock(ReentrantReadWriteLock lock) {
        sync = lock.sync;
    }

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-获取锁方法(默认共享模式)*/
    public void lock() {
        sync.acquireShared(1);
    }

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-获取锁方法(支持中断机制)*/
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-尝试获取锁(一般模式)*/
    public boolean tryLock() {
        return sync.tryReadLock();
    }


    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-尝试获取锁(支持超时机制)*/
    public boolean tryLock(long timeout, TimeUnit unit)
    throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-释放锁*/
    public void unlock() {
        sync.releaseShared(1);
    }

    /** ReentrantReadWriteLock锁-ReadLock读锁内部类-条件变量*/
    public Condition newCondition() {
        throw new UnsupportedOperationException();
    }


    public String toString() {
        int r = sync.getReadLockCount();
        return super.toString() +
            "[Read locks = " + r + "]";
    }
}
  • 实现方式:主要是基于Lock接口来实现的ReadLock锁,同时通过构造方法指定了一个内部同步器Sync,其对应的方法都是基于AQS基础同步器的共享模式来实现的。
  • 获取锁方式:主要提供了4个方法来实现锁的获取,其中:
    • 无参数的lock()方法: 获取锁的一般模式,主要是基于AQS基础同步器中的acquireShared(int arg)方法来实现,其核心处理逻辑是doAcquireShared(int arg)方法
    • 无参数的lockInterruptibly()方法:获取可中断锁的模式,主要是基于AQS基础同步器中的acquireSharedInterruptibly(int arg)方法来实现,其核心处理逻辑是doAcquireSharedInterruptibly(int arg)方法
    • 无参数的tryLock()方法:尝试获取ReadLock锁,主要是基于AQS基础同步器中的tryReadLock()方法来实现,其核心处理逻辑是自旋+compareAndSetState()方法的加持CAS操作的。
    • 有参数的ryLock()方法:尝试获取ReadLock锁,支持超时机制,主要是基于AQS基础同步器中的tryAcquireSharedNanos(int arg, long nanosTimeout)方法来实现,其核心处理逻辑是在doAcquireSharedNanos(int arg, long nanosTimeout)方法,主要是自旋+shouldParkAfterFailedAcquire()方法的加持CAS操作的。
  • 释放锁方式:主要提供了一个unlock()方法来实现ReadLock 的释放,其中本质是基于AQS基础同步器中的releaseShared(int arg) 方法,其中核心处理逻辑是doReleaseShared()的方法,其核心处理是自旋+compareAndSetWaitStatus()方法来加持CAS操作的。

2.6 基于Lock接口实现WriteLock写锁内部类

/** ReentrantReadWriteLock锁-基于Lock接口实现WriteLock写锁内部类*/
public static class WriteLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = -4992448646407690164L;

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-同步器*/
    private final Sync sync;

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-内部构造方法*/
    protected WriteLock(ReentrantReadWriteLock lock) {
        sync = lock.sync;
    }

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-获取锁方法(独占模式)*/
    public void lock() {
        sync.acquire(1);
    }


    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-获取锁方法(可中断)*/
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-获取锁方法(一般模式)*/
    public boolean tryLock( ) {
        return sync.tryWriteLock();
    }

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-获取锁方法(支持超时机制)*/
    public boolean tryLock(long timeout, TimeUnit unit)
    throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }


    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-释放锁*/
    public void unlock() {
        sync.release(1);
    }



    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-条件变量*/
    public Condition newCondition() {
        return sync.newCondition();
    }


    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-是否独占判断*/
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /** ReentrantReadWriteLock锁-WriteLock写锁内部类-统计数量*/
    public int getHoldCount() {
        return sync.getWriteHoldCount();
    }
}
  • 实现方式:主要是基于Lock接口来实现的WriteLock锁,同时通过构造方法指定了一个内部同步器Sync,其对应的方法都是基于AQS基础同步器的独占模式来实现的。
  • 获取锁式:主要提供了4个方法来实现锁的获取,其中:
    • 无参数的lock()方法: 获取WriteLock锁的一般模式,主要是基于AQS基础同步器中的acquire(int arg)方法来实现,其核心处理逻辑是acquireQueued(final Node node, int arg)方法
    • 无参数的lockInterruptibly()方法:获取WriteLock锁可中断锁的模式,主要是基于AQS基础同步器中的acquireInterruptibly(int arg)方法来实现,其核心处理逻辑是doAcquireInterruptibly(int arg)方法
    • 无参数的tryLock()方法:尝试获取WriteLock锁,主要是基于AQS基础同步器中的tryReadLock()方法来实现,其核心处理逻辑是自旋+compareAndSetState()方法的加持CAS操作的。
    • 有参数的ryLock()方法:尝试获取WriteLock锁,支持超时机制,主要是基于AQS基础同步器中的tryAcquireNanos(int arg, long nanosTimeout)方法来实现,其核心处理逻辑是在doAcquireNanos(int arg, long nanosTimeout)方法,主要是自旋+shouldParkAfterFailedAcquire()方法的加持CAS操作的。
  • 释放锁方式:主要提供了一个unlock()方法来实现ReadLock 的释放,其中本质是基于AQS基础同步器中unparkSuccessor(Node node)方法,主要是通过compareAndSetWaitStatus()方法来加持CAS操作的。

3. 具体实现

public class ReentrantReadWriteLock
    implements ReadWriteLock, java.io.Serializable {

        private static final long serialVersionUID = -6992448646407690164L;

        /** ReentrantReadWriteLock锁-内部ReadLock类 */
        private final ReentrantReadWriteLock.ReadLock readerLock;

        /** ReentrantReadWriteLock锁-内部WriteLock类 */
        private final ReentrantReadWriteLock.WriteLock writerLock;

        /** ReentrantReadWriteLock锁-内部同步器 */
        final Sync sync; 

        /** ReentrantReadWriteLock锁-实例化Unsafe支持 */
        private static final sun.misc.Unsafe UNSAFE;

        /** ReentrantReadWriteLock锁-线程偏移量 */
        private static final long TID_OFFSET;

        /** ReentrantReadWriteLock锁-基于AQS封装内部同步器 */
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = 6317671515068378041L;

            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;

            private transient ThreadLocalHoldCounter readHolds;

            private transient HoldCounter cachedHoldCounter;

            private transient Thread firstReader = null;
            private transient int firstReaderHoldCount;

            Sync() {
                readHolds = new ThreadLocalHoldCounter();
                setState(getState()); // ensures visibility of readHolds
            }
            abstract boolean readerShouldBlock();

            abstract boolean writerShouldBlock();

            //... 其他代码
        }



        /** ReentrantReadWriteLock锁-无参数构造(默认非公平模式) */
        public ReentrantReadWriteLock() {
            this(false);
        }

        /** ReentrantReadWriteLock锁-有参数构造(可选公平/非公平模式) */
        public ReentrantReadWriteLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
            readerLock = new ReadLock(this);
            writerLock = new WriteLock(this);
        }

        /** ReentrantReadWriteLock锁-获取写锁 */
        public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }      
        /** ReentrantReadWriteLock锁-获取读锁 */
        public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
        /** ReentrantReadWriteLock锁-获取线程变量 */
        public final boolean isFair() {
            return sync instanceof FairSync;
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        protected Thread getOwner() {
            return sync.getOwner();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public int getReadLockCount() {
            return sync.getReadLockCount();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public boolean isWriteLocked() {
            return sync.isWriteLocked();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public boolean isWriteLockedByCurrentThread() {
            return sync.isHeldExclusively();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public int getWriteHoldCount() {
            return sync.getWriteHoldCount();
        }
        /** ReentrantReadWriteLock锁-获取线程变量 */
        public int getReadHoldCount() {
            return sync.getReadHoldCount();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        protected Collection<Thread> getQueuedWriterThreads() {
            return sync.getExclusiveQueuedThreads();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        protected Collection<Thread> getQueuedReaderThreads() {
            return sync.getSharedQueuedThreads();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public final boolean hasQueuedThreads() {
            return sync.hasQueuedThreads();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public final boolean hasQueuedThread(Thread thread) {
            return sync.isQueued(thread);
        }
        /** ReentrantReadWriteLock锁-获取线程变量 */
        public final int getQueueLength() {
            return sync.getQueueLength();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        protected Collection<Thread> getQueuedThreads() {
            return sync.getQueuedThreads();
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public boolean hasWaiters(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        protected Collection<Thread> getWaitingThreads(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        public int getWaitQueueLength(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
        }

        /** ReentrantReadWriteLock锁-获取线程变量 */
        static final long getThreadId(Thread thread) {
            return UNSAFE.getLongVolatile(thread, TID_OFFSET);
        }

        /** ReentrantReadWriteLock锁-反射机制实例化Unsafe */
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> tk = Thread.class;
                TID_OFFSET = UNSAFE.objectFieldOffset
                    (tk.getDeclaredField("tid"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
  • 读写锁同步器:主要提供了2个构造方法来实现读写锁的管理,其中:
    • 无参数构造方法:默认非公平模式,主要是通过this关键字来指定的
    • 有参数构造方法:可选公平/非公平模式,依据指定传入公平标记fair来实例化NonfairSync非公平同步器和FairSync公平同步器,其中,当fair=true时,是公平平模式;否则,当fair=false时为非公平模式。同时,实例化ReadLock和WriteLock对象。
  • 读锁主要方法:对于读锁的操作,一般我们只需要关注readLock()方法和类似getReadXX() 方法,其中:
    • readLock()方法:主要用于获取和实现读锁ReadLock
    • getReadHoldCount() 方法:主要用于统计某个线程对于读锁的持有情况
    • getReadLockCount() 方法:主要用于统计某个线程对于读锁的获取的次数
  • 写锁主要方法:对于读锁的操作,一般我们只需要关注readLock()方法和类似包含xWriteXX() 方法,其中:
    • writeLock() 方法:主要用于获取和实现写锁WriteLock
    • getWriteHoldCount()方法:主要用于统计当前线程对于写锁WriteLock的持有情况
    • isWriteLocked()方法:主要用于判断某个线程对于写锁WriteLock的是否加锁
    • isWriteLockedByCurrentThread() 方法:主要用于判断当前线程对于写锁WriteLock的是否加锁
  • 条件队列操作方法:还提供了一系列的对于条件变量队列操作方法,其中:
    • getQueuedWriterThreads() 方法:主要用于获取线程等待获取写锁WriteLock的情况
    • getQueuedReaderThreads() 方法:主要用于获取线程等待获取读锁ReadLock的情况
    • getQueuedThreads()方法:主要用于获取线程等待获取读锁ReadLock和写锁WriteLock的情况
    • getQueueLength() 方法:主要用于获取线程等待获取读锁ReadLock和写锁WriteLock的个数
  • 等待队列操作方法: 还提供了一系列的对于等待队列操作方法,其中:
    • getWaitingThreads() 方法:主要依据Condition来用于获取等待队列中所有的线程的对象
    • getWaitQueueLength() 方法:主要依据Condition来用于获取等待队列中所有的线程对于写锁WriteLock的相关的个数
  • 其他方法:除此之外,还提供了一些队列操作的常规方法,其中:
    • hasQueuedThread() 方法:主要依据单个Thread对象用于获取线程是否有获取读锁ReadLock和写锁WriteLock的情况
    • hasQueuedThreads() 方法:主要用于获取多个线程是否有获取读锁ReadLock和写锁WriteLock的情况
    • hasWaiters()方法:主要依据Condition来用于判断等待队列中所有的线程对于写锁WriteLock的相关情况
    • isFair() 方法:用于判断是否公平模式
    • getThreadId()方法:获取线程编号ID,主要是通过指定UNSAFE.getLongVolatile(thread, TID_OFFSET)实现。

<br />综上所述,ReentrantReadWriteLock锁是基于AQS基础同步器的共享模式和独享模式共同孵化的产物,支持公平/非公平模式,其中的ReadLock和WriteLock是基于同一个AQS基础同步器来实现,维护了共用状态变量机制。

写在最后

通过对Java领域中,JDK内部提供的各种锁的实现来看,一直围绕的核心主要还是基于AQS基础同步器来实现的,但是AQS基础同步器不是一种非它不可的技术标准规范,更多的只是一套技术参考指南。

但是,实际上,Java对于锁的实现与运用远远不止这些,还有相位器(Phaser)和交换器(Exchanger),以及在Java JDK1.8版本之前并发容器ConcurrentHashMap中使用的分段锁(Segment)。

不论是何种实现和应用,在Java并发编程领域来讲,都是围绕线程安全问题的角度去考虑的,只是针对于各种各样的业务场景做的具体的实现。

一定意义上来讲,对线程加锁只是并发编程的实现方式之一,相对于实际应用来说,Java领域中的锁都只是一种单一应用的锁,只是给我们掌握Java并发编程提供一种思想没,三言两语也不可能详尽。

到此为止,这算是对于Java领域中并发锁的最终章,文中表述均为个人看法和个人理解,如有不到之处,忘请谅解也请给予批评指正。

最后,技术研究之路任重而道远,愿我们熬的每一个通宵,都撑得起我们想在这条路上走下去的勇气,未来仍然可期,与各位程序编程君共勉!

版权声明:本文为博主原创文章,遵循相关版权协议,如若转载或者分享请附上原文出处链接和链接来源。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容