ReentrantLock 源码逐行超详细注释

我已按照是什么→为什么→怎么做→被谁调用的逻辑,对ReentrantLock源码每一行代码添加极致详细注释,同时嵌入Mermaid流程图/关系图说明核心流程、组件关联,全程以注释+markdown图表形式输出,可直接嵌入源码使用。

一、完整源码 + 逐行终极注释

/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain
 */

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;

/**
 * 【是什么】:可重入互斥锁,实现Lock接口,支持同一线程多次获取锁
 * 【为什么】:替代synchronized关键字,提供可中断、可超时、公平/非公平、条件队列等高级功能
 * 【核心特性】:可重入、独占、支持公平/非公平模式、基于AQS实现
 * 【怎么做】:通过AQS的state状态计数实现重入,通过CLH队列实现线程排队
 * 【被谁调用】:JUC并发工具类、业务代码、线程池、并发集合等
 */
public class ReentrantLock implements Lock, java.io.Serializable {
    // 序列化UID:是什么-唯一标识序列化版本;为什么-保证序列化兼容性;怎么做-JVM自动使用;被谁调用-序列化机制
    private static final long serialVersionUID = 7373984872572414699L;

    /**
     * 同步器:是什么-锁的核心实现组件,继承AQS;为什么-封装锁的所有同步逻辑;怎么做-提供公平/非公平两种实现;被谁调用-ReentrantLock所有方法
     */
    private final Sync sync;

    /**
     * 【是什么】:AQS同步器的抽象基类,独占锁核心实现
     * 【为什么】:抽离公平/非公平锁的公共逻辑,减少代码冗余
     * 【怎么做】:继承AQS,用state表示锁重入次数,0=无锁,>0=持有锁
     * 【被谁调用】:FairSync、NonfairSync继承,ReentrantLock持有
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        // 序列化UID:是什么-同步器序列化版本;为什么-兼容序列化;怎么做-固定值;被谁调用-JVM
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 【是什么】:抽象加锁方法;【为什么】:让公平/非公平锁自定义加锁逻辑;【怎么做】:子类实现;【被谁调用】:ReentrantLock.lock()
         */
        abstract void lock();

        /**
         * 【是什么】:非公平尝试获取锁(核心方法)
         * 【为什么】:非公平锁直接抢占锁,无需排队,提升吞吐量
         * 【怎么做】:CAS修改AQS state状态,判断是否重入
         * 【被谁调用】:NonfairSync.tryAcquire()、ReentrantLock.tryLock()
         * @param acquires 获取锁的增量(固定1)
         * @return true=获取成功,false=失败
         */
        final boolean nonfairTryAcquire(int acquires) {
            // 1. 获取当前执行线程:是什么-拿到调用方法的线程;为什么-判断是否重入;怎么做-Thread.currentThread();被谁调用-当前锁竞争线程
            final Thread current = Thread.currentThread();
            // 2. 获取AQS状态:是什么-state=0无锁,>0持有锁;为什么-判断锁状态;怎么做-AQS.getState();被谁调用-AQS
            int c = getState();
            // 3. 无锁状态:是什么-锁未被任何线程持有;为什么-可以直接抢占锁;怎么做-CAS修改state
            if (c == 0) {
                // 4. CAS原子修改state:是什么-原子操作,无锁竞争;为什么-保证多线程安全;怎么做-unsafe.compareAndSwapInt;被谁调用-CPU指令
                if (compareAndSetState(0, acquires)) {
                    // 5. 设置锁持有线程:是什么-标记当前线程独占锁;为什么-支持可重入;怎么做-AQS.setExclusiveOwnerThread;被谁调用-AQS
                    setExclusiveOwnerThread(current);
                    // 6. 返回成功:是什么-获取锁完成;为什么-通知上层加锁成功;怎么做-return true;被谁调用-调用方
                    return true;
                }
            }
            // 7. 可重入判断:是什么-当前线程已持有锁;为什么-支持同一线程多次加锁;怎么做-对比持有线程
            else if (current == getExclusiveOwnerThread()) {
                // 8. 计算新的重入次数:是什么-state+1;为什么-记录重入层级;怎么做-加法运算;被谁调用-当前持有线程
                int nextc = c + acquires;
                // 9. 溢出判断:是什么-超过int最大值;为什么-防止计数异常;怎么做-判断负数;被谁调用-锁重入超限场景
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                // 10. 更新重入次数:是什么-无需CAS,单线程独占;为什么-只有当前线程能修改;怎么做-AQS.setState;被谁调用-AQS
                setState(nextc);
                // 11. 重入获取锁成功
                return true;
            }
            // 12. 获取锁失败:是什么-锁被其他线程持有;为什么-进入排队;怎么做-return false;被谁调用-AQS.acquire()
            return false;
        }

        /**
         * 【是什么】:释放锁(核心方法)
         * 【为什么】:释放锁资源,唤醒排队线程
         * 【怎么做】:state减1,为0时完全释放锁
         * 【被谁调用】:ReentrantLock.unlock() → AQS.release()
         * @param releases 释放增量(固定1)
         * @return true=完全释放,false=重入未释放完
         */
        protected final boolean tryRelease(int releases) {
            // 1. 计算释放后的state:是什么-重入次数-1;为什么-逐层释放锁;怎么做-减法;被谁调用-当前持有线程
            int c = getState() - releases;
            // 2. 合法性校验:是什么-只有锁持有者能释放;为什么-防止非法释放;怎么做-对比线程;被谁调用-非法调用线程
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            // 3. 标记是否完全释放:是什么-true=锁空闲;为什么-通知AQS唤醒排队线程;怎么做-布尔变量;被谁调用-AQS
            boolean free = false;
            // 4. 完全释放判断:是什么-state=0;为什么-锁无持有者;怎么做-判断c=0
            if (c == 0) {
                free = true;
                // 5. 清空持有线程:是什么-释放锁所有权;为什么-标记锁空闲;怎么做-AQS.setExclusiveOwnerThread(null)
                setExclusiveOwnerThread(null);
            }
            // 6. 更新state:是什么-保存重入次数;为什么-记录锁状态;怎么做-AQS.setState
            setState(c);
            // 7. 返回释放结果
            return free;
        }

        /**
         * 【是什么】:判断当前线程是否独占锁
         * 【为什么】:支持重入校验、状态查询
         * 【怎么做】:对比AQS持有线程与当前线程
         * 【被谁调用】:ReentrantLock.isHeldByCurrentThread()
         */
        protected final boolean isHeldExclusively() {
            // 直接返回线程对比结果:是什么-独占判断;为什么-AQS要求实现;怎么做-==判断;被谁调用-AQS
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        /**
         * 【是什么】:创建条件队列
         * 【为什么】:实现wait/notify高级功能
         * 【怎么做】:返回AQS的ConditionObject
         * 【被谁调用】:ReentrantLock.newCondition()
         */
        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // ========== 状态查询方法(被谁调用:ReentrantLock对外暴露的查询方法) ==========
        /**
         * 【是什么】:获取锁持有线程;【为什么】:监控/调试;【怎么做】:state=0返回null,否则返回持有线程;【被谁调用】ReentrantLock.getOwner()
         */
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        /**
         * 【是什么】:获取重入次数;【为什么】:调试/监控;【怎么做】:独占则返回state,否则0;【被谁调用】ReentrantLock.getHoldCount()
         */
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        /**
         * 【是什么】:判断是否加锁;【为什么】:状态查询;【怎么做】:state≠0;【被谁调用】ReentrantLock.isLocked()
         */
        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * 【是什么】:反序列化重置锁状态
         * 【为什么】:反序列化后锁必须为无锁状态
         * 【怎么做】:重置state=0
         * 【被谁调用】:JVM反序列化机制
         */
        private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // 强制重置为无锁
        }
    }

    /**
     * 【是什么】:非公平锁同步器(默认实现)
     * 【为什么】:吞吐量高,线程可直接抢占锁,无需排队
     * 【怎么做】:继承Sync,重写lock/tryAcquire
     * 【被谁调用】:new ReentrantLock()/new ReentrantLock(false)
     */
    static final class NonfairSync extends Sync {
        // 序列化UID
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * 【是什么】:非公平加锁
         * 【为什么】:先直接CAS抢占锁,失败再排队,提升效率
         * 【怎么做】:先CAS抢锁,失败调用AQS.acquire()排队
         * 【被谁调用】:ReentrantLock.lock()
         */
        final void lock() {
            // 1. 第一次抢占:是什么-无条件CAS抢锁;为什么-非公平核心;怎么做-compareAndSetState;被谁调用-当前竞争线程
            if (compareAndSetState(0, 1))
                // 2. 抢锁成功:设置当前线程为持有者
                setExclusiveOwnerThread(Thread.currentThread());
            else
                // 3. 抢锁失败:是什么-进入AQS排队流程;为什么-等待锁释放;怎么做-AQS.acquire(1);被谁调用-AQS
                acquire(1);
        }

        /**
         * 【是什么】:尝试获取锁;【为什么】:AQS要求实现;【怎么做】:调用父类nonfairTryAcquire;【被谁调用】AQS.acquire()
         */
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * 【是什么】:公平锁同步器
     * 【为什么】:保证线程按排队顺序获取锁,避免线程饥饿
     * 【怎么做】:继承Sync,重写lock/tryAcquire,必须检查队列
     * 【被谁调用】:new ReentrantLock(true)
     */
    static final class FairSync extends Sync {
        // 序列化UID
        private static final long serialVersionUID = -3000897897090466540L;

        /**
         * 【是什么】:公平加锁
         * 【为什么】:不允许抢占,必须直接排队,保证公平
         * 【怎么做】:直接调用AQS.acquire(),不做CAS抢占
         * 【被谁调用】:ReentrantLock.lock()
         */
        final void lock() {
            // 直接进入排队流程:是什么-公平锁核心;为什么-禁止插队;怎么做-AQS.acquire(1);被谁调用-AQS
            acquire(1);
        }

        /**
         * 【是什么】:公平尝试获取锁
         * 【为什么】:必须检查队列,只有自己是队首才能抢锁
         * 【怎么做】:判断hasQueuedPredecessors()+CAS
         * 【被谁调用】:AQS.acquire()
         */
        protected final boolean tryAcquire(int acquires) {
            // 1. 获取当前线程
            final Thread current = Thread.currentThread();
            // 2. 获取锁状态
            int c = getState();
            // 3. 无锁状态
            if (c == 0) {
                // 4. 公平核心:是什么-判断是否有前置排队线程;为什么-保证FIFO;怎么做-AQS.hasQueuedPredecessors();被谁调用-AQS
                if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 5. 可重入逻辑(与非公平一致)
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

    // ==================== ReentrantLock 构造方法 ====================
    /**
     * 【是什么】:无参构造(默认非公平锁)
     * 【为什么】:非公平锁吞吐量更高,满足绝大多数场景
     * 【怎么做】:初始化NonfairSync
     * 【被谁调用】:业务代码new ReentrantLock()
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * 【是什么】:带公平参数的构造
     * 【为什么】:支持自定义公平/非公平模式
     * 【怎么做】:true=FairSync,false=NonfairSync
     * 【被谁调用】:需要公平锁的业务场景
     * @param fair true=公平锁,false=非公平锁
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    // ==================== Lock 接口实现(对外核心方法) ====================
    /**
     * 【是什么】:阻塞加锁(不可中断)
     * 【为什么】:最常用的加锁方式
     * 【怎么做】:调用sync.lock()
     * 【被谁调用】:业务代码、并发工具类
     */
    public void lock() {
        sync.lock();
    }

    /**
     * 【是什么】:可中断阻塞加锁
     * 【为什么】:支持线程中断,避免无限阻塞
     * 【怎么做】:调用AQS.acquireInterruptibly(1)
     * 【被谁调用】:需要中断响应的场景
     */
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /**
     * 【是什么】:非阻塞尝试加锁(立即返回)
     * 【为什么】:不排队,立即获取结果
     * 【怎么做】:调用nonfairTryAcquire(1)
     * 【被谁调用】:尝试加锁场景
     */
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    /**
     * 【是什么】:超时尝试加锁
     * 【为什么】:避免无限阻塞,支持超时退出
     * 【怎么做】:调用AQS.tryAcquireNanos
     * 【被谁调用】:限时等待场景
     */
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

    /**
     * 【是什么】:释放锁
     * 【为什么】:释放锁资源,唤醒排队线程
     * 【怎么做】:调用AQS.release(1)
     * 【被谁调用】:业务代码finally块
     */
    public void unlock() {
        sync.release(1);
    }

    /**
     * 【是什么】:创建条件变量
     * 【为什么】:实现线程等待/通知
     * 【怎么做】:调用sync.newCondition()
     * 【被谁调用】:生产者-消费者模式
     */
    public Condition newCondition() {
        return sync.newCondition();
    }

    // ==================== 状态查询方法 ====================
    public int getHoldCount() { return sync.getHoldCount(); }
    public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); }
    public boolean isLocked() { return sync.isLocked(); }
    public final boolean isFair() { return sync instanceof FairSync; }
    protected Thread getOwner() { return sync.getOwner(); }
    public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
    public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); }
    public final int getQueueLength() { return sync.getQueueLength(); }
    protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); }

    // ==================== 条件队列查询方法 ====================
    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);
    }

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

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

    /**
     * 【是什么】:打印锁状态
     * 【为什么】:调试/日志输出
     * 【怎么做】:拼接锁状态+持有线程
     * 【被谁调用】:日志打印
     */
    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]");
    }
}

二、核心组件关联图(Mermaid)

graph TD ReentrantLock -->|持有| Sync[Sync 抽象同步器<br>继承AQS] Sync -->|被继承| NonfairSync[NonfairSync 非公平锁<br>默认实现] Sync -->|被继承| FairSync[FairSync 公平锁<br>带参构造] Sync -->|依赖| AQS[AbstractQueuedSynchronizer<br>核心:state+CLH队列] ReentrantLock -->|对外方法| LockAPI[lock/unlock/tryLock] ReentrantLock -->|条件队列| Condition[ConditionObject<br>等待/通知]

三、非公平锁加锁流程图(核心流程)

flowchart TD A["调用lock()"] --> B["CAS尝试抢占锁 state=0→1"] B -->|成功| C["设置当前线程为独占线程<br/>加锁完成"] B -->|失败| D["调用AQS.acquire(1)"] D --> E["执行tryAcquire尝试获取锁"] E -->|成功| F["加锁完成"] E -->|失败| G["线程进入CLH队列排队<br/>阻塞等待"] G --> H["锁释放后被唤醒<br/>重新竞争锁"]

四、公平锁加锁流程图(核心流程)

flowchart TD A["调用lock()"] --> B["直接调用AQS.acquire(1)"] B --> C["执行公平tryAcquire"] C --> D["判断hasQueuedPredecessors<br/>是否有前置排队线程"] D -->|有排队| E["获取失败,进入队列"] D -->|无排队| F["CAS抢锁→设置独占线程"] E --> G["阻塞等待→队首时被唤醒"] G --> C

五、锁释放流程图(通用)

flowchart TD A["调用unlock()"] --> B["执行tryRelease state-1"] B --> C["校验:当前线程是否为持有者"] C -->|否| D["抛出IllegalMonitorStateException"] C -->|是| E["state=0?"] E -->|否| F["更新state,未完全释放"] E -->|是| G["清空持有线程<br/>完全释放锁"] G --> H["AQS唤醒CLH队列队首线程"]

六、核心知识点总结(markdown)

1. 是什么

ReentrantLockJDK1.5提供的可重入独占锁,基于AQS实现,实现Lock接口,支持公平/非公平两种模式。

2. 为什么

  • synchronized更灵活:支持可中断、可超时、条件队列、公平模式
  • 可重入:同一线程可多次加锁,避免死锁
  • 非公平锁吞吐量远高于公平锁

3. 怎么做

  • 重入实现:用AQSstate计数,加锁+1,释放-1,state=0表示无锁
  • 非公平锁:直接CAS抢占锁,失败再排队
  • 公平锁:必须检查队列,禁止插队,严格FIFO
  • 线程排队:基于AQS的CLH双向队列实现阻塞/唤醒

4. 被谁调用

  • 业务代码:并发安全控制
  • JUC组件:线程池、并发集合、CountDownLatch等
  • 中间件:分布式锁、限流框架底层
posted @ 2026-03-05 17:13  先弓  阅读(0)  评论(0)    收藏  举报