关于java:Java并发编程解析-解析Java领域中并发锁之ReentrantReadWriteLock锁的设计思想与实现原理-二

3次阅读

共计 30034 个字符,预计需要花费 76 分钟才能阅读完成。

天穹之边,浩瀚之挚,眰恦之美;悟心悟性,虎头蛇尾,惟善惟道!—— 朝槿《朝槿兮年说》


写在结尾

在并发编程畛域,有两大外围问题:一个是互斥,即同一时刻只容许一个线程访问共享资源;另一个是同步,即线程之间如何通信、合作。
次要起因是,对于多线程实现实现并发,始终以来,多线程都存在 2 个问题:

  • 线程之间内存共享,须要通过加锁进行管制,然而加锁会导致性能降落,同时简单的加锁机制也会减少编程编码难度
  • 过多线程造成线程之间的上下文切换,导致效率低下

因而,在并发编程畛域中,始终有一个很重要的设计准则:“不要通过内存共享来实现通信,而应该通过通信来实现内存共享。”
简略来说,就是尽可能通过音讯通信,而不是内存共享来实现过程或者线程之间的同步。

关健术语

本文用到的一些要害词语以及罕用术语,次要如下:

  • 并发(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):两个或两个以上的过程或线程在运行过程中协同步调,按预约的先后秩序运行。即就是线程之间如何通信、合作的问题。

针对对于这两大外围问题,利用管程是可能解决和实现的,因而能够说,管程是并发编程的万能钥匙。
尽管,Java 在基于语法层面 (synchronized 关键字) 实现了对管程技术, 然而从应用形式和性能上来说,内置锁 (synchronized 关键字) 的粒度绝对过大,不反对超时和中断等问题。
为了补救这些问题,从 JDK 层面对其“反复造轮子”,在 JDK 外部对其从新设计和定义,甚至实现了新的个性。
在 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 畛域中, 同步器是专门为多线程并发设计的同步机制,次要是多线程并发执行时线程之间通过某种共享状态来实现同步,只有当状态满足这种条件时线程才往下执行的一种同步机制。

一个规范的 AQS 同步器次要有同步状态机制,期待队列,条件队列,独占模式,共享模式等五大外围因素组成。
在 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 来标识该节点是共享模式

咱们能够失去一个比拟通用的并发同步工具根底模型,大抵蕴含如下几个内容,其中:

  • 条件变量(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 根底形象队列同步器实现的一种并发管制工具类。

通过 ReentrantReadWriteLock 类能获取读锁和写锁,它的读锁是能够多线程共享的共享锁,而它的写锁是排他锁,在被占时不容许其余线程再抢占操作。

1. 设计思维

一般来说,在一些非凡的场景中,比方对于数据的读和写操作,为进步并发性能,总会引入共享锁和独享锁来独特组成一把锁,通常状况下,咱们把这类锁成为读写锁 (ReadWriteLock)。
简略来说,就是次要思考读和写操作,读操作不会批改数据,能够利用多个线程进行读操作,个别采纳共享锁实现;而写操作会扭转数据自身,只能容许一个线程进行操作,因而采纳独享锁实现。
读写锁(ReadWriteLock) 最大的一个特点就是在外部保护一对锁,一把读锁(ReadLock),一把写锁(WriteLock)。其中,对于线程持有的状况来说,简略能够总结为“读共享,写独占”。

1.1 读写锁的根本实践

尽管读写锁 (ReadWriteLock) 之间是有关系的:同一时刻不容许读锁和写锁同时被抢占,二者之间是互斥的。
假如当初有 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)线程开释完持有的写锁,能力持续往下执行。

从肯定意义上讲,依据读写锁操作的状况的性质剖析,获取读锁和写锁的条件能够大抵总结为:

  • 获取读锁的条件:以后任何线程没有胜利获取且曾经持有写锁的状况,才可能获取并持有读锁。
  • 获取写锁的条件:以后任何线程没有胜利获取且曾经持有写锁和读锁的状况,才可能获取并持有写锁。

然而在某些状况下,可能存在某个线程曾经获取并持有读锁,心愿可能获取写锁,并且在曾经开释读锁时,通常状况下咱们称之为读写锁的降级。
当然,有降级就会有降级,与之对应的就是读写锁的降级,次要形容的是某个线程曾经获取并持有写锁,心愿可能获取读锁,并且曾经开释写锁。
一般来说,对于读写锁的降级与降级,咱们个别须要留神的以下两个问题,其中:

  • 读写锁的降级:指的是读锁降级为写锁的状况,须要满足某个线程必须是惟一领有读锁的线程的条件,否则无奈降级。
  • 读写锁的降级:指的是写锁降级为读锁的状况,没有什么条件限度,写锁是独占锁,其持有线程是惟一的且不会存在读锁持有线程的状况,能够间接平滑降级读锁。

    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 根底同步器实现读写锁的共享一个共享变量。
其中,最偏心的形式设计形式就是读锁与写锁各自占用 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_)实现。

综上所述,ReentrantReadWriteLock 锁是基于 AQS 根底同步器的共享模式和独享模式独特孵化的产物,反对偏心 / 非偏心模式,其中的 ReadLock 和 WriteLock 是基于同一个 AQS 根底同步器来实现,保护了共用状态变量机制。

写在最初

通过对 Java 畛域中,JDK 外部提供的各种锁的实现来看,始终围绕的外围次要还是基于 AQS 根底同步器来实现的,然而 AQS 根底同步器不是一种非它不可的技术标准规范,更多的只是一套技术参考指南。

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

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

肯定意义上来讲,对线程加锁只是并发编程的实现形式之一,绝对于理论利用来说,Java 畛域中的锁都只是一种繁多利用的锁,只是给咱们把握 Java 并发编程提供一种思维没,喋喋不休也不可能详尽。

到此为止,这算是对于 Java 畛域中并发锁的最终章,文中表述均为集体认识和集体了解,如有不到之处,忘请谅解也请给予批评指正。

最初,技术钻研之路任重而道远,愿咱们熬的每一个通宵,都撑得起咱们想在这条路上走上来的勇气,将来依然可期,与各位程序编程君共勉!

正文完
 0