• Java 并发编程解析 | 基于 JDK 源码解析 Java 领域中 ReentrantLock 锁的设计思想与实现原理


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

    最近我从cnaaa.com购买了云服务器

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

    img

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

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

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

    img

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

    img
    一个标准的 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 来标识该节点是共享模式

    我们可以得到一个比较通用的并发同步工具基础模型,大致包含如下几个内容,其中:
    img

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

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

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

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

    img

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

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

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

    三.ReentrantLock (可重入锁) 的设计与实现

    在 Java 领域中,ReentrantLock (可重入锁) 是针对于 Java 多线程并发控制中对一个线程可以多次对某个锁进行加锁操作,主要是基于内置的 AQS 基础抽象队列同步器实现的一种并发控制工具类。

    img
    一般来说,对于同一个线程是否可以重复占有同一个锁对象的角度来分,大致主要可以分为可重入锁与不可重入锁。其中:

    • 可重入锁:一个线程可以多次抢占同一个锁,也就意味着能够支持一个线程对资源的重复加锁,或者说,一个线程可以多次进入同一个锁所同步的临界区代码块。
    • 不可重入锁:一个线程只能抢占一次同一个锁,也就意味着在同一时刻只能有一个线程获取到锁,而其他获取锁的线程只能等待,只有拥有锁的线程释放了锁后,其他的线程才能够获取锁。

    ReentrantLock 是 JDK 中显式锁一个主要基于 Lock 接口 API 实现的基础实现类,拥有与内置锁 (synchronized) 相同的并发性和内存语义,同时提供了限时抢占、可中断抢占等一些高级锁特性。
    除此之外,ReentrantLock 基于内置的 AQS 基础抽象队列同步器实现,在线程参与锁资源竞争比较激烈的场景下,能表现出比内置锁较佳的性能。
    而且,ReentrantLock 是一种独占锁,在独占模式下只能逐一使用锁,也就是说,任意时刻最多只会有一个线程持有锁的控制权。

    1. 设计思想

    img

    ReentrantLock 类最早是在 JDK1.5 版本提供的,从设计思想上来看,主要包括同步器工作模式,获取锁方法,释放锁方法以及定义 Condition 队列方法等 4 个核心要素。其中:

    • 实现 Lock 接口 :主要基于 Lock 接口 API 实现对应方法,拥有与内置锁 (synchronized) 相同的并发性和内存语义,用于支持和解决解决互斥问题。
    • 同步器工作模式:基于 AQS 基础抽象队列同步器封装内置实现一个静态的内置同步器抽象类,然后基于这个抽象类分别实现了公平同步器和非公平同步器,用来指定和描述同步器工作模式是公平模式还是非公平模式。
    • 公平 / 非公平模式:主要描述的是多个线程在同时获取锁时是否按照先到先得的顺序获取锁,如果是则为公平模式,否则为非公平模式。
    • 获取锁方法:主要定义了一个 lock () 方法来获取锁,表示假如锁已经被其他线程占有或持有,其当前获取锁的线程则进入等待状态。
    • 释放锁方法:主要定义了一个 unlock () 方法来释放锁,表示假如锁已经被其他线程放弃或释放,其当前获取锁的线程则获得该锁。
    • 定义 Condition 队列操作方法: 主要是基于 Condition 接口来定义一个方法实现锁的条件机制,用于支持线程的阻塞和唤醒功能即就是解决同步问题,也就是我们说的线程间的通信方式。
    • 定义等待队列操作方法: 主要是依据条件队列来时进行对应的操作,间接适配 AQS 基础同步器中对于等待队列的功能,保证获取锁的顺序的公平性

    2. 基本实现

    img

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

    public class ReentrantLock implements Lock, java.io.Serializable {
    
        private static final long serialVersionUID = 7373984872572414699 L;
    
        /**
         * ReentrantLock锁-定义支持同步器实现
         */
        private final Sync sync;
    
        /**
         * ReentrantLock锁-基于AQS定义支持同步器实现
         */
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860 L;
    
            /**
             * ReentrantLock锁-定义支持同步器Sync获取锁方法
             */
            abstract void lock();
    				
            //......其他方法代码
        }
    
        /**
         * ReentrantLock锁-构造同步器默认工作模式(默认非公平模式)
         */
        public ReentrantLock() {
            sync = new NonfairSync();
        }
    
        /**
         * ReentrantLock锁-构造同步器指定工作模式(可选公平/非公平模式)
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    
        /**
         * ReentrantLock锁-获取锁(普通模式)
         */
        public void lock() {
            sync.lock();
        }
    
        /**
         * ReentrantLock锁-释放锁
         */
        public void unlock() {
            sync.release(1);
        }
    
        /**
         * ReentrantLock锁-创建锁的条件机制
         */
        public Condition newCondition() {
            return sync.newCondition();
        }
    
        //......其他方法代码
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 内部同步器:基于 AQS 基础同步器封装和定义了一个静态内部 Sync 抽象类,其中抽象了一个内置锁 lock () 方法
    • 同步器工作模式:提供了 2 个构造方法,其中无参数构造方法表示的是默认的工作模式,有参数构造方法主要依据参数来实现指定的工作模式
    • 获取锁: 主要是提供了 lock () 方法,调用的静态内部 Sync 抽象类内置锁 lock () 方法,而本质上是 AQS 同步器中的 acquire () 方法
    • 释放锁: 主要是提供了 unlock () 方法,而本质上是调用的 AQS 同步器中的 release () 方法
    • 创建条件队列: 主要是基于 Condition 接口定义了 newCondition () 方法,调用的静态内部 Sync 抽象类 ewCondition () 方法,而本质上是调用的 AQS 同步器中的 ConditionObject 中的 newCondition () 方法
    2.1 基于 AQS 同步器封装静态内部 Sync 抽象类
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860L;
    
            /**
             * ReentrantLock锁-内部同步器Sync的内置加锁方法
             */
            abstract void lock();
    
            /**
             * ReentrantLock锁-内部同步器Sync的非公平获取锁
             */
            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
            /**
             * ReentrantLock锁-内部同步器Sync的尝试释放
             */
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    
    
            /**
             * ReentrantLock锁-内部同步器Sync的检查线程是否独占
             */
            protected final boolean isHeldExclusively() {
                // While we must in general read state before owner,
                // we don't need to do so to check if current thread is owner
                return getExclusiveOwnerThread() == Thread.currentThread();
            }
    
            /**
             * ReentrantLock锁-内部同步器Sync的条件机制
             */
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
    
    
            /**
             * ReentrantLock锁-内部同步器Sync的判断锁持有者
             */
            final Thread getOwner() {
                return getState() == 0 ? null : getExclusiveOwnerThread();
            }
    
            /**
             * ReentrantLock锁-内部同步器Sync的独占状态
             */
            final int getHoldCount() {
                return isHeldExclusively() ? getState() : 0;
            }
    
            /**
             * ReentrantLock锁-内部同步器Sync的是否被锁
             */
            final boolean isLocked() {
                return getState() != 0;
            }
    
            /**
             * ReentrantLock锁-内部同步器Sync的流化处理对象
             */
            private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                setState(0); // reset to unlocked state
            }
    				
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • Sync 类:FairSync 公平同步器和 NonfairSync 非公平同步器的抽象父类。
    • 校验 isHeldExclusively () 方法: ReentrantLock 锁是属于独占模式,需要当前锁持有线程与当前线程是否一致
    • nonfairTryAcquire () 方法: 一般主要用于非公平模式获取锁,其核心是 compareAndSetState 方法和 setExclusiveOwnerThread 方法
    • tryRelease () 方法: 其公平 / 非公平模式都是通过 ryRelease () 来释放锁操作
    • newCondition () 方法: 基于 AQS 同步器的 ConditionObject 对象封装实现,提供给 ReentrantLock 类使用
    • 私有 readObject () 方法:对于输入的对象进行流化处理

    特别需要注意的是,我们需要重点关注 nonfairTryAcquire () 方法和 tryRelease () 方法,其中:

    • 获取非公平锁 nonfairTryAcquire () 方法:主要是用于获取 AQS 的状态变量 status,其默认取值范围是 0 和 1,其中,0 表示未被加锁,1 表示已经被加锁
      • 如果状态变量 status=0,使用 compareAndSetState 方法进行 CAS 原子修改操作,把状态变量修改为 1,并且通过 setExclusiveOwnerThread 设置当前线程为锁的持有线程
      • 如果状态变量 status=1,表示当前线程为锁的持有线程,正在进入锁重入操作,状态变量累加 1,超过重入次数时,会抛出 throw new Error (“Maximum lock count exceeded”)
    • 释放锁 tryRelease () 方法:主要是检查当前线程是否为锁持有线程,随后 AQS 同步器状态变量减 1,如果不是 throw new IllegalMonitorStateException ()
      • 如果状态变量 status=0,表示锁已经释放成功,通过 setExclusiveOwnerThread 设置锁的持有线程为 null,也就是置空锁的持有线程
      • 如果状态变量 status !=0, 需要状态变量递减 1 即可,直到锁已经释放成功
    2.2 基于 Sync 抽象类封装 FairSync 公平同步器
        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            /**
             * ReentrantLock锁-公平模式-获取锁
             */
            final void lock() {
                acquire(1);
            }
    
            /**
             * ReentrantLock锁-公平模式-尝试获取锁
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 实现方式: 主要基于 AQS 封装的内部静态抽象 Sync 同步类实现,使用的 AQS 的独占模式。
    • 主要方法: 主要提供了 lock () 和 tryAcquire () 方法,其严格意义上来说,仅仅只是实现了 tryAcquire () 方法,但是最关键的使用 hasQueuedPredecessors 来保证了锁的公平性。
    • 锁获取方式: 主要是采用完全通过队列来实现实现公平机制,即就是检查是否存在等待队列,如果队列之中已经存在其他线程,直接放弃操作。
    2.3 基于 Sync 抽象类封装 NonfairSync 非公平同步器
        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * ReentrantLock锁-非公平模式-获取锁
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            /**
             * ReentrantLock锁-非公平模式-尝试获取锁
             */
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 实现方式: 主要基于 AQS 封装的内部静态抽象 Sync 同步类实现,使用的 AQS 的独占模式。
    • 主要方法: 主要提供了 lock () 和 tryAcquire () 方法,其严格意义上来说,仅仅只是实现了 tryAcquire () 方法,直接调用了 Sync 同步类的 nonfairTryAcquire () 方法。
    • 锁获取方式: 主要是采用闯入策略来打破锁的公平,也就是一般准备获取锁的线程会先尝试获取锁,失败之后才进入队列中。

    3. 具体实现

    img

    在 ReentrantLock 类的 JDK1.8 版本中,对于 ReentrantLock 的具体实现如下:

    public class ReentrantLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = 7373984872572414699 L;
        /** Synchronizer providing all implementation mechanics */
        private final Sync sync;
    
        /**
         * ReentrantLock锁-基于AQS定义支持同步器实现
         */
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860 L;
    
            /**
             * ReentrantLock锁-定义支持同步器Sync获取锁方法
             */
            abstract void lock();
    				
            //......其他方法代码
        }
    
        /**
         * ReentrantLock锁-构造同步器默认工作模式(默认非公平模式)
         */
        public ReentrantLock() {
            sync = new NonfairSync();
        }
    
        /**
         * ReentrantLock锁-构造同步器指定工作模式(可选公平/非公平模式)
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    
        /**
         * ReentrantLock锁-获取锁(普通模式)
         */
        public void lock() {
            sync.lock();
        }
    
        /**
         * ReentrantLock锁-释放锁
         */
        public void unlock() {
            sync.release(1);
        }
    
        /**
         * ReentrantLock锁-创建锁的条件机制
         */
        public Condition newCondition() {
            return sync.newCondition();
        }
    		
        /**
         * ReentrantLock锁-获取锁(支持可中断机制)
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
    
        /**
         * ReentrantLock锁-尝试获取锁(普通模式)
         */
        public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
        }
    
        /**
         * ReentrantLock锁-尝试获取锁(支持超时)
         */
        public boolean tryLock(long timeout, TimeUnit unit)
        throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
    
        /**
         * ReentrantLock锁-统计当前线程所持有数量
         */
        public int getHoldCount() {
            return sync.getHoldCount();
        }
    
    
        /**
         * ReentrantLock锁-检测当前线程是否独占
         */
        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }
    
        /**
         * ReentrantLock锁-检测是否被加锁
         */
        public boolean isLocked() {
            return sync.isLocked();
        }
    
        /**
         * ReentrantLock锁-检测是否公平模式
         */
        public final boolean isFair() {
            return sync instanceof FairSync;
        }
    
        /**
         * ReentrantLock锁-获取当前锁持有线程
         */
        protected Thread getOwner() {
            return sync.getOwner();
        }
    
        /**
         * ReentrantLock锁-检测轮询线程是否存在队列中
         */
        public final boolean hasQueuedThreads() {
            return sync.hasQueuedThreads();
        }
    
        /**
         * ReentrantLock锁-检测线程是否存在队列中
         */
        public final boolean hasQueuedThread(Thread thread) {
            return sync.isQueued(thread);
        }
    
        /**
         * ReentrantLock锁-获取队列数量
         */
        public final int getQueueLength() {
            return sync.getQueueLength();
        }
    
        /**
         * ReentrantLock锁-获取队列中的所有线程
         */
        protected Collection < Thread > getQueuedThreads() {
            return sync.getQueuedThreads();
        }
    
        /**
         * ReentrantLock锁-检测存在条件队列是否入队状态
         */
        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);
        }
    
        /**
         * ReentrantLock锁-获取等待队列的长度
         */
        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);
        }
    
        /**
         * ReentrantLock锁-获取等待队列的线程对象
         */
        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);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 获取锁的方法:主要提供了一般模式 lock () 方法,支持可中断机制 lockInterruptibly () 方法,无参数 tryLock () 方法以及有参数的支持超时机制的 tryLock (long timeout, TimeUnit unit) 方法
    • 释放锁的方法:主要是 unlock () 方法,间接调用是内部同步器中的 release () 方法
    • 条件队列操作:主要提供了获取队列中的线程对象 getQueuedThreads (),检测队列入队 hasWaiters (Condition condition) 方法,以及
    • 等待队列操作:主要提供了获取队列中的线程对象 getWaitingThreads (Condition condition),检测队列入队 hasQueuedThread (Thread thread) 方法,以及获取队列长度 getQueueLength () 方法和 getWaitingThreads (Condition condition) 方法
    • 其他检测判断:主要有判断是否公平模式 isFair () 方法,是否当前线程独占 isHeldByCurrentThread () 方法,以及是否加锁 isLocked () 等

    需要注意的是,在 JDK1.8 版本之后,对于 ReentrantLock 的实现有些细微的变化,感兴趣的可自行参考相关版本的源码进行对比分析。

    综上所述,从一定意义上讲,ReentrantLock 是一种可重入的独占 (互斥) 锁,属于 AQS 基础抽象队列同步器中独占模式孵化的产物,支持公平模式与非公平模式,默认采用非公平模式。

  • 相关阅读:
    C++11
    GPT-4o:未来语言模型的典范
    安装Mysql报错:Could not create or access the registry key needed for the...
    【面试经典150 | 哈希表】存在重复元素 II
    前端基础入门
    Elasticsearch 安装及启动【Windows】
    第20章 Netty
    线性DP问题
    x265线程池机制和并行编码机制分析
    小咖啡馆也能撬动大生意
  • 原文地址:https://blog.csdn.net/weixin_53641036/article/details/126992330