Java 中 ReentrantLock 的实现原理是什么?

📅 发布时间:2026/7/7 7:36:59 👁️ 浏览次数:
Java 中 ReentrantLock 的实现原理是什么?
Java 中 ReentrantLock 的实现原理ReentrantLock 是 Java 并发包java.util.concurrent.locks中提供的可重入互斥锁它基于AQSAbstractQueuedSynchronizer抽象队列同步器实现。一、核心架构ReentrantLock ├── Sync (内部抽象类继承自 AQS) │ ├── NonfairSync (非公平锁实现) │ └── FairSync (公平锁实现) └── ConditionObject (条件变量实现)二、AQS 核心原理AQS 是 ReentrantLock 的基础其核心包含1. 状态变量// AQS 中的核心字段privatevolatileintstate;// 同步状态0 表示未锁定0 表示重入次数2. 等待队列// CLH 队列变种用于存储等待获取锁的线程privatetransientvolatileNodehead;privatetransientvolatileNodetail;staticfinalclassNode{intwaitStatus;// 等待状态Nodeprev;// 前驱节点Nodenext;// 后继节点Threadthread;// 等待的线程NodenextWaiter;// 条件队列的下一个节点}三、ReentrantLock 源码分析1. 基本结构publicclassReentrantLockimplementsLock,java.io.Serializable{privatefinalSyncsync;// 同步器抽象类abstractstaticclassSyncextendsAbstractQueuedSynchronizer{abstractbooleaninitialTryLock();// 非公平尝试获取锁finalbooleannonfairTryAcquire(intacquires){finalThreadcurrentThread.currentThread();intcgetState();if(c0){// state 为 0尝试 CAS 设置为 1if(compareAndSetState(0,acquires)){setExclusiveOwnerThread(current);returntrue;}}elseif(currentgetExclusiveOwnerThread()){// 可重入当前线程已持有锁state 1intnextccacquires;if(nextc0)// overflowthrownewError(Maximum lock count exceeded);setState(nextc);returntrue;}returnfalse;}// 释放锁protectedfinalbooleantryRelease(intreleases){intcgetState()-releases;if(Thread.currentThread()!getExclusiveOwnerThread())thrownewIllegalMonitorStateException();booleanfreefalse;if(c0){freetrue;setExclusiveOwnerThread(null);}setState(c);returnfree;}}// 非公平锁staticfinalclassNonfairSyncextendsSync{finalbooleaninitialTryLock(){if(compareAndSetState(0,1)){// 直接尝试 CAS 抢锁setExclusiveOwnerThread(Thread.currentThread());returntrue;}returnfalse;}protectedfinalbooleantryAcquire(intacquires){returnnonfairTryAcquire(acquires);}}// 公平锁staticfinalclassFairSyncextendsSync{finalbooleaninitialTryLock(){ThreadcurrentThread.currentThread();intcgetState();if(c0){// 公平锁检查队列中是否有前驱节点if(!hasQueuedPredecessors()compareAndSetState(0,1)){setExclusiveOwnerThread(current);returntrue;}}elseif(currentgetExclusiveOwnerThread()){intnextcc1;if(nextc0)thrownewError(Maximum lock count exceeded);setState(nextc);returntrue;}returnfalse;}protectedfinalbooleantryAcquire(intacquires){returninitialTryLock();}}}2. 加锁流程lock()publicvoidlock(){sync.acquire(1);// 调用 AQS 的 acquire 方法}// AQS 中的 acquire 方法publicfinalvoidacquire(intarg){// 1. 尝试获取锁if(!tryAcquire(arg)// 2. 获取失败加入等待队列acquireQueued(addWaiter(Node.EXCLUSIVE),arg))selfInterrupt();// 3. 中断当前线程}流程图线程调用 lock() ↓ tryAcquire() 尝试获取锁 ↓ 成功 → 是 → 获取锁继续执行 ↓ 否 addWaiter() 创建节点加入队列尾部 ↓ acquireQueued() 在队列中等待 ↓ 前驱节点是 head ↓ 是 → tryAcquire() 再次尝试获取锁 ↓ 成功 → 是 → 设置为 head返回 ↓ 否 shouldParkAfterFailedAcquire() 检查是否需要阻塞 ↓ 需要 → 是 → parkAndCheckInterrupt() 阻塞线程 ↓ 被唤醒 → 重新尝试获取锁3. 解锁流程unlock()publicvoidunlock(){sync.release(1);// 调用 AQS 的 release 方法}// AQS 中的 release 方法publicfinalbooleanrelease(intarg){// 1. 尝试释放锁if(tryRelease(arg)){Nodehhead;if(h!nullh.waitStatus!0)// 2. 唤醒后继节点unparkSuccessor(h);returntrue;}returnfalse;}四、公平锁 vs 非公平锁特性公平锁非公平锁获取顺序按请求顺序 FIFO允许插队吞吐量较低较高饥饿问题无可能存在默认实现new ReentrantLock(true)new ReentrantLock()非公平锁的优势// 非公平锁在释放锁时新来的线程可以直接 CAS 抢锁// 而不需要排队减少了线程上下文切换staticfinalclassNonfairSyncextendsSync{finalbooleaninitialTryLock(){if(compareAndSetState(0,1)){// 直接尝试抢锁setExclusiveOwnerThread(Thread.currentThread());returntrue;}returnfalse;}}五、可重入性实现// 同一线程可以多次获取锁ReentrantLocklocknewReentrantLock();lock.lock();// state 1lock.lock();// state 2 (重入)lock.unlock();// state 1lock.unlock();// state 0 (真正释放)重入判断elseif(currentgetExclusiveOwnerThread()){// 当前线程已持有锁state 1intnextccacquires;setState(nextc);returntrue;}六、Condition 条件变量ReentrantLocklocknewReentrantLock();Conditionconditionlock.newCondition();// 等待lock.lock();try{while(!conditionMet){condition.await();// 释放锁并等待}}finally{lock.unlock();}// 通知lock.lock();try{condition.signal();// 唤醒一个等待线程}finally{lock.unlock();}Condition 实现原理每个Condition维护一个单独的等待队列await()释放锁加入条件队列阻塞signal()将条件队列节点转移到同步队列七、完整示例importjava.util.concurrent.locks.ReentrantLock;publicclassReentrantLockDemo{privatestaticfinalReentrantLocklocknewReentrantLock();privatestaticintcount0;publicstaticvoidmain(String[]args)throwsInterruptedException{// 创建10个线程for(inti0;i10;i){newThread(()-{for(intj0;j1000;j){lock.lock();try{count;// 临界区}finally{lock.unlock();// 必须在 finally 中释放}}}).start();}Thread.sleep(1000);System.out.println(最终计数: count);// 输出 10000}}八、ReentrantLock vs synchronized特性ReentrantLocksynchronized实现方式基于 AQSJVM 层面实现可重入性支持支持公平性可选公平/非公平非公平响应中断支持lockInterruptibly不支持超时获取支持tryLock不支持条件变量支持多个 Condition只有一个 wait/notify释放方式必须手动 unlock自动释放九、总结ReentrantLock 的核心原理基于 AQS利用 AQS 的 state 变量和 CLH 队列实现同步CAS 操作使用 CAS 原子操作修改 state 状态可重入通过判断当前线程是否已持有锁实现公平/非公平通过不同的 Sync 实现提供两种策略条件变量支持多个 Condition 实现复杂的等待/通知机制ReentrantLock 提供了比 synchronized 更灵活、更强大的锁功能适用于需要高级特性的并发场景。