【源码】【Java并发】【ReentrantLock】适合中学者体质的ReentrantLock源码阅读

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD

🔥 2025本人正在沉淀中... 博客更新速度++

👍 欢迎点赞、收藏、关注,跟上我的更新节奏

📚欢迎订阅专栏,专栏名《在2B工作中寻求并发是否搞错了什么》
因为本文说的是ReentrantLock源码,因此会默认,大家对AQS有基本的了解(比如同步队列、条件队列大概> 长啥样?)。

不懂AQS的小朋友们,你们好呀!也欢迎先看看这篇

【源码】【Java并发】【AQS】从ReentrantLock、Semaphore、CutDownLunch、CyclicBarrier看AQS源码

基本结构分析

Sync抽象类

ReentrantLock的内部抽象类,继承自AQS

Sync支持了锁的可重入、锁的释放、提供了获取ConditinObject(可以将线程阻塞唤醒)。

咱们这里就重点说下锁的获取和释放:

定义锁的释放逻辑 :实现 tryRelease()方法,通过state变量记录重入次数(释放时递减)。

具体获取锁的逻辑: 定义lock抽象方法,需要子类FairSyncNonfairSync实现。

独占锁实现

这里要说ReentrantLock下锁的实现,是基于AQSstate字段实现的。

java 复制代码
/**
 * The synchronization state.
 */
private volatile int state;

ReentrantLock的state,值为0表示没有线程占有锁,值为1表示这个锁已经被占有。

获取锁ReentrantLock会尝试通casstate从0改为1,就是获取锁成功的意思。下面以非公平获取,nonfairTryAcquire实现为例子:

java 复制代码
// ReentrantLock.Sync#nonfairTryAcquire
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // state为0表示没有线程占有锁,我们当前线程可以尝试占有
    if (c == 0) {
        // cas将state由0改为1
        if (compareAndSetState(0, acquires)) { 
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 锁的可重入的逻辑:如果现在持有锁的线程,是当前锁的话,state++
    else if (current == getExclusiveOwnerThread()) {
        // state++
        int nextc = c + acquires;
        if (nextc < 0) 
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

释放锁 :因为有锁的重入的情况(锁的重入会导致state++),释放锁是将state--(而不是将state从1改为0),减到state为0就表示锁已经被释放。

java 复制代码
// ReentrantLock.Sync#tryRelease
// ReentrantLock实现中,releases是1
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;	// 将state减1
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    // 减少后state变为0,说明锁可以释放了
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);	// 修改state数量
    return free;
}

protected final void setState(int newState) {
    state = newState;
}

// === 下面证明为啥tryRelease方法的入参releases是1 === 
// ReentrantLock#unlock
// 释放锁
public void unlock() {
    // 调用到AQS的release方法
    sync.release(1);
}
// AbstractQueuedSynchronizer#release
// arg的值就是1
public final boolean release(int arg) {
    // 调用子类(ReentrantLock.Sync)实现tryRelease方法,arg传的是1。
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

普通lock方法

java 复制代码
// ReentrantLock#lock
public void lock() {
    sync.lock();
}

公平和非公平的实现,我们可以看到,区别就在,非公平的实现,多了先,尝试先获取锁了下。

java 复制代码
// ReentrantLock.NonfairSync#lock
final void lock() {
    acquire(1);
}

// ReentrantLock.FairSync#lock
final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

acquire方法,这里我们重点看子类的具体实现tryAcquire方法。

java 复制代码
// AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&		// 调用子类具体实现的tryAcquire方法
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

非公平的实现tryAcquire

java 复制代码
// ReentrantLock.NonfairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

// ReentrantLock.Sync#nonfairTryAcquire
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // 当前没有线程占有锁,尝试cas获取锁。
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 可重入锁,state++。
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) 
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

公平的实现tryAcquire方法

java 复制代码
// ReentrantLock.FairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // 当前没有线程占有锁,获取锁
    if (c == 0) {
        // 和非公平多了一个判断hasQueuedPredecessors
        // 判断当前线程是否需要排队(即检查同步队列中是否有其他线程比它更早申请锁)。
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 可重入锁,state++
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

深入AQS源码,看hasQueuedPredecessors, 判断当前线程是否需要排队。

不懂AQS同步队列的小朋友,你们有难了!嘿嘿,如果不懂AQS的,建议先了解下AQS。(疑似主播二次广告植入)

【源码】【Java并发】【AQS】从ReentrantLock、Semaphore、CutDownLunch、CyclicBarrier看AQS源码

什么样的情况不用排队?同步队列中,下一个Node是当前线程的情况:

java 复制代码
public final boolean hasQueuedPredecessors() {
    Node t = tail; 
    Node h = head;
    Node s;
    return h != t &&
        ((s = h.next) == null || s.thread != Thread.currentThread());
}

线程中断概念

中断相关知识补充,如果你已经知道中断相关的知识,可以跳过。

稍后,你可能会看到这个方法Thread.interrupted(),你一定会好奇,芝士什么意思勒?它有什么用?

arduino 复制代码
private final boolean parkAndCheckInterrupt() {
    LockSupport.park(this);
    return Thread.interrupted();	// Thread.interrupted()????
}

那聪明的你,一定要知道,什么是中断?这里主播会简单介绍下的:

Java 的线程中断(Thread Interruption) 是一种协作式机制,用于通知线程"有人希望它停止当前的操作",但线程是否停止、何时停止以及如何停止,完全由线程自身决定。中断机制的核心是通过标志位传递信号,而不是强制终止线程。

是用来替代Tread.stop()这种不安全的方法的。

简单案例1:

java 复制代码
Thread worker = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) { // 检查中断标志
        // 执行任务逻辑
        System.out.println("Working...");
    }
    System.out.println("Thread gracefully stopped.");
});
worker.start();

// 外部请求中断
worker.interrupt();

简单案例2:处理阻塞的中断

java 复制代码
public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
        try {
            while (true) {
                System.out.println("线程即将进入阻塞...");
                Thread.sleep(1000); // 模拟阻塞操作
            }
        } catch (InterruptedException e) {
            System.out.println("线程在阻塞时被中断,捕获异常!");
            Thread.currentThread().interrupt(); // 重新设置中断标志
        }
    });

    thread.start();
    Thread.sleep(10);
    thread.interrupt(); // 中断阻塞中的线程
}

ok呀,聪明的你一定对线程中断有一定的了解了,下面是下Thread的一些关于线程中断的方法:

  1. interrupt() :设置线程的中断标志位,即使线程正在阻塞状态(如sleep),也会触发 InterruptedException
  2. isInterrupted() :检查线程的中断标志位(不清除标志位)。
  3. Thread.interrupted() :检查当前线程的中断标志位,并清除标志位(静态方法)。

现在,你看懂这个方法了吗?

java 复制代码
private final boolean parkAndCheckInterrupt() {
    LockSupport.park(this);
    return Thread.interrupted();	// 返回当前线程是否被中断,并清除标志位
}

可中断lock

其实和普通的lock是差不多的,多了对线程是否发生中断的判断,如果发生中断的话,就抛出中断异常。

java 复制代码
// ReentrantLock#lockInterruptibly
public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}

acquireInterruptibly方法,多了对中断的判断。

java 复制代码
// AbstractQueuedSynchronizer#acquireInterruptibly
public final void acquireInterruptibly(int arg)
        throws InterruptedException {
    // 判断当前线程是否被中断,如果被中断,就抛出中断异常
    if (Thread.interrupted())
        throw new InterruptedException();
    // tryAcquire子类具体实现,上面普通lock说过了。
    if (!tryAcquire(arg))
        doAcquireInterruptibly(arg);	// 👈这里重点看看AQS是怎么做的。
}

doAcquireInterruptibly方法,shouldParkAfterFailedAcquire方法和parkAndCheckInterrupt为true的话,就抛出中断异常。

java 复制代码
private void doAcquireInterruptibly(int arg)
    throws InterruptedException {
    final Node node = addWaiter(Node.EXCLUSIVE);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; 
                failed = false;
                return;
            }
            // 当parkAndCheckInterrupt也返回为true的话,就抛出中断异常
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

// parkAndCheckInterrupt方法
private final boolean parkAndCheckInterrupt() {
    // 挂起线程
    LockSupport.park(this);
    // 线程恢复后,返回该线程是否被中断,并将标志位重置
    return Thread.interrupted();
}

对比普通lock的acquireQueued的只是记录下发生了线程中断,然后再自我中断(因为标志位被重置为false了)。而doAcquireInterruptibly是直接抛出异常。

java 复制代码
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; 
                failed = false;
                return interrupted;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;	// 这里记录下线程发生了中断
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

// acquireQueued返回为true会发生什么? ---> 自我中断
public final void acquire(int arg) {
    // 如果获取锁失败 且 acquireQueued时,线程发生了中断
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();	// 自我中断
}

// 自我中断 (因为标志位,在acquireQueued时,被重置为fasle了)
static void selfInterrupt() {
    Thread.currentThread().interrupt();
}

超时lock

超时lock入口,tryLock方法:

java 复制代码
// ReentrantLock#tryLock
public boolean tryLock(long timeout, TimeUnit unit)
        throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

tryAcquireNanos方法,上面的文章说过了子类的实现tryAcquire方法,这里重点看AQS是怎么实现doAcquireNanos方法。

java 复制代码
// AbstractQueuedSynchronizer#tryAcquireNanos
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    // 同中断的lock,发生中断,直接抛中断异常
    if (Thread.interrupted())
        throw new InterruptedException();
    return tryAcquire(arg) ||
        doAcquireNanos(arg, nanosTimeout); // 重点看AQS的doAcquireNanos实现
}

doAcquireNanos方法,

java 复制代码
// AbstractQueuedSynchronizer#doAcquireNanos
private boolean doAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    if (nanosTimeout <= 0L)
        return false;
    // 计算截止时间
    final long deadline = System.nanoTime() + nanosTimeout;
    final Node node = addWaiter(Node.EXCLUSIVE);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null;
                failed = false;
                return true;
            }
            nanosTimeout = deadline - System.nanoTime();
            // 超时返回false
            if (nanosTimeout <= 0L)
                return false;
            // spinForTimeoutThreshold是1000L,如果挂起的太短就不挂起了,影响性能
            if (shouldParkAfterFailedAcquire(p, node) &&
                nanosTimeout > spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);	// 挂起线程
            // 发生了中断的话,就抛出中断异常
            if (Thread.interrupted())
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

🤔我们可以看到,和中断的lock相比,这里多了时间的计算,和挂起线程一段时间。

锁释lock

方法入口unlock:

java 复制代码
// ReentrantLock#unlock
public void unlock() {
    sync.release(1);
}

调用AQS的release方法,这里重点看子类的实现tryRelease方法。

java 复制代码
// AbstractQueuedSynchronizer#release
public final boolean release(int arg) {
    // 调用子类实现的tryRelease方法,返回true,就唤醒别的线程去抢锁。
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);		
        return true;
    }
    return false;
}

子类Sync实现tryRelease方法:

java 复制代码
// ReentrantLock.Sync#tryRelease
protected final boolean tryRelease(int releases) {
    // 将state--
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    // state为0,说明没有线程占有锁
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    // 更新state数量
    setState(c);
    return free;
}

线程间通信实现源码

我们的ReentrantLock直接使用了AQS提供的线程通信,下面再分析下去,就是在分析AQS了。

先来个简单的用法,热热身体吧!

java 复制代码
    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    lock.lock();
                    condition.await();
                    System.out.println("sub thread:" + Thread.currentThread() + " get lock");
                } catch (InterruptedException e) {
                    System.out.println("sub thread interrupted");
                } finally {
                    lock.unlock();
                }
            }).start();
        }

        Thread.sleep(1000);
        lock.lock();
        try {
            System.out.println("main thread singleAll");
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

输出结果

shell 复制代码
main thread singleAll
sub thread:Thread[Thread-0,5,main] get lock
sub thread:Thread[Thread-1,5,main] get lock
sub thread:Thread[Thread-2,5,main] get lock
sub thread:Thread[Thread-3,5,main] get lock
sub thread:Thread[Thread-4,5,main] get lock

Conditon接口

java 复制代码
public interface Condition {
    // ======== 等待相关 ===========
    void await() throws InterruptedException; // 等待直到被通知或中断
    void awaitUninterruptibly();              // 不可中断的等待
    long awaitNanos(long nanosTimeout) throws InterruptedException; // 纳秒级超时等待
    boolean await(long time, TimeUnit unit) throws InterruptedException; // 带时间单位的超时等待
    boolean awaitUntil(Date deadline) throws InterruptedException; // 等待到指定时间点
    // ======== 通知相关 ===========
    void signal();   // 唤醒一个等待线程
    void signalAll(); // 唤醒所有等待线程
}

AQS中的ConditionObject实现

ReentrantLock是只是获取了这个ConditionObject

java 复制代码
// java.util.concurrent.locks.ReentrantLock.Sync#newCondition
final ConditionObject newCondition() {
    return new ConditionObject();
}

awat方法

await方法

java 复制代码
public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    Node node = addConditionWaiter();	// 向条件队列新增Node
    int savedState = fullyRelease(node);	// 释放锁,savedState是释放锁之前,state数值,1
    int interruptMode = 0;
    // 判断是否在同步队列中,不在就挂起线程。
    while (!isOnSyncQueue(node)) {
        LockSupport.park(this);
        // 1.发生中断退出循环 2.给interruptMode赋值 THROW_IE(-1) signal发生前, REINTERRUPT(1) signal发生后
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    // 抢占锁发生中断(acquireQueued方法返回是否发生中断)
    // ============且=============
    // 中断原中断模式不是 THROW_IE,将模式改为 REINTERRUPT(避免覆盖原有的中断语义)
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
        interruptMode = REINTERRUPT;
    // 清除无效节点
    if (node.nextWaiter != null) 
        unlinkCancelledWaiters();
    // 处理中断结果
    // THROW_IE:抛出 InterruptedException,通知调用者等待被中断。
    // REINTERRUPT:重新标记线程的中断状态(调用 Thread.currentThread().interrupt()),但不抛出异常。
    if (interruptMode != 0)
        reportInterruptAfterWait(interruptMode);
}

addConditionWaiter方法:向条件队列中新增一个Node。

java 复制代码
// AbstractQueuedSynchronizer.ConditionObject#addConditionWaiter
private Node addConditionWaiter() {
    Node t = lastWaiter;
    // 清除为CANCEL状态的尾部Node
    if (t != null && t.waitStatus != Node.CONDITION) {
        // 从firstWaiter开始,向后删除waitStatus为Node.CONDITION的Node
        unlinkCancelledWaiters();
        t = lastWaiter;
    }
    // 新增1个waitStatus为Node.CONDITION的Node
    Node node = new Node(Thread.currentThread(), Node.CONDITION);
    if (t == null)
        firstWaiter = node;
    else
        t.nextWaiter = node;
    lastWaiter = node;
    return node;
}

fullyRelease方法:释放锁资源

java 复制代码
final int fullyRelease(Node node) {
    boolean failed = true;
    try {
        int savedState = getState();
        // 释放锁
        if (release(savedState)) {
            failed = false;
            return savedState;
        } else {
            throw new IllegalMonitorStateException();
        }
    } finally {
        if (failed)
            node.waitStatus = Node.CANCELLED;
    }
}

isOnSyncQueue方法:判断是否在同步队列中

java 复制代码
final boolean isOnSyncQueue(Node node) {
    // 不在同步队列中:Node等待状态为Node.CONDITION 或 Node.next为空(新增Node,条件队列不用prev这个字段,同步队列这个prev字段不可能为空)
    if (node.waitStatus == Node.CONDITION || node.prev == null)
        return false;
    // 如果有Node.next != null,那就是在同步队列中(因为条件队的下一个Node,用的是Node的nextWaiter字段)
    if (node.next != null) 
        return true;
    // 节点可能已设置前驱指针,但尚未真正入同步队列(因CAS操作可能失败)
    // 从后向前找,找到就返回true,没有就返回fasle
    return findNodeFromTail(node);
}

findNodeFromTail方法

java 复制代码
private boolean findNodeFromTail(Node node) {
    Node t = tail;
    // 从后向前找新增Node,找到就返回true,没有就返回fasle
    for (;;) {
        if (t == node)
            return true;
        if (t == null)
            return false;
        t = t.prev;
    }
}

checkInterruptWhileWaiting:判断是等待前中断,还是等待后中断

java 复制代码
// 检查线程在条件队列(Condition Queue)中等待时是否被中断
private int checkInterruptWhileWaiting(Node node) {
    return Thread.interrupted() ?            // 检查并清除中断状态
        (transferAfterCancelledWait(node) ? // 如果中断发生,尝试转移节点到同步队列
            THROW_IE :                      // 中断在 signal 前:需抛出中断异常
            REINTERRUPT) :                  // 中断在 signal 后:需重设中断状态
        0;                                  // 未发生中断,返回0
}

private static final int THROW_IE    = -1;
private static final int REINTERRUPT =  1;

transferAfterCancelledWait

java 复制代码
final boolean transferAfterCancelledWait(Node node) {
    // CAS将Node的等待状态改为0,加入同步队列
    if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
        enq(node);
        return true;  // 中断发生在single前
    }
    // 如果 CAS 失败,循环检查节点是否已被其他线程加入同步队列
    // CAS失败说明,其他线程正在转移节点,必须通过 while (!isOnSyncQueue(node)) 等待其完成
    // Thread.yield()是为了在 "自旋等待其他线程完成操作" 时,平衡 CPU 资源消耗与等待效率,避免忙等待的极端性能损耗。
    while (!isOnSyncQueue(node))
        Thread.yield();
    return false;  // 中断发生在single后
}

reportInterruptAfterWait:根据interruptMode对中断进行不同的处理

java 复制代码
private void reportInterruptAfterWait(int interruptMode)
    throws InterruptedException {
    // 中断在 signal 前:需抛出中断异常
    if (interruptMode == THROW_IE)
        throw new InterruptedException();
    // 中断在 signal 后:需重设中断状态
    else if (interruptMode == REINTERRUPT)
        selfInterrupt();
}

signal方法

就是唤醒条件队列第一个有效节点。

java 复制代码
public final void signal() {
    // 判断是不是当前线程持有锁
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    // 条件队列中有节点,则执行具体唤醒逻辑
    if (first != null)
        doSignal(first);
}

doSignal,遍历条件队列,找到第一个未被取消的节点,并将其转移到同步队列以唤醒对应线程。

java 复制代码
private void doSignal(Node first) {
    do {
        // 更新条件队列头节点,并断开当前节点的链接(其实就是移除条件队列)
        if ( (firstWaiter = first.nextWaiter) == null)
            lastWaiter = null;
        first.nextWaiter = null;
    // 尝试将当前节点转移到同步队列
    } while (!transferForSignal(first) &&	// 若转移失败,继续尝试下一个节点
             (first = firstWaiter) != null); // 更新 first 为下一个节点,直到队列为空
}

将节点由条件队列转同步队列

java 复制代码
final boolean transferForSignal(Node node) {
    // CAS修改当前节点等待状态,由Node.CONDITION(-2)修改为0
    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
        return false;

    // 当前节点进入同步队列中
    Node p = enq(node);
    int ws = p.waitStatus;
    // 唤醒线程:等待状态为CANCELLED(1)或者 CAS修改等待状态到Node.SIGNAL(-1)
    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        LockSupport.unpark(node.thread);
    return true;
}

signalAll方法

让我们看看signalAll和signal的区别有哪里不同吧!

方法入口:

signalAll方法,这里和signal差不多嘛,那要我们看看具体的doSignalAll有什么区别了。

java 复制代码
public final void signalAll() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignalAll(first);
}

doSignalAll方法,遍历条件队列,只要Node不为null,就唤醒。

java 复制代码
private void doSignalAll(Node first) {
    lastWaiter = firstWaiter = null;
    do {
        Node next = first.nextWaiter;
        first.nextWaiter = null;
        // 转为同步队列
        transferForSignal(first);
        first = next;
    } while (first != null);
}

后话

本篇,从ReentrantLock的两大功能独占锁线程通信的源码角度来看ReentrantLock

聪明的你一定学会了很多吧( ̄▽ ̄)"

相关推荐
葫芦和十三4 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp5 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑5 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯6 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan8 小时前
多Agent之间的区别
后端
青石路10 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充10 小时前
1.面向对象设计思想
后端
IT_陈寒11 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro11 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端
要阿尔卑斯吗11 小时前
提示词优化启示:为什么“按顺序输出“比“关键度评分“更有效
后端