【源码】【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

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

相关推荐
qq_485015214 分钟前
Java网络编程干货
java·网络·php
bobz9654 分钟前
supervisord 的使用
后端
大道无形我有型5 分钟前
📖 Spring 事务机制超详细讲解(哥们专属)
后端
Re2756 分钟前
springboot源码分析--自动配置流程
spring boot·后端
Piper蛋窝9 分钟前
Go 1.2 相比 Go1.1 有哪些值得注意的改动?
后端·go
努力的搬砖人.12 分钟前
java爬虫案例
java·经验分享·后端
Miraitowa_cheems22 分钟前
JAVA SE 自我总结
java·开发语言·javase
老马啸西风23 分钟前
java 开源中文的繁简体转换 opencc4j-03-简体还是繁体,你说了算!
java
海风极客24 分钟前
一文搞懂JSON和HJSON
前端·后端·面试
南雨北斗25 分钟前
2.单独下载和配置PHP环境
后端