目录一、AQS 核心原理回顾二、可重入独占锁完整代码仿 ReentrantLock 非公平锁三、测试代码验证重入、阻塞、Condition 等待唤醒四、关键方法流程拆解1. 获取锁 sync.acquire(1)2. 释放锁 sync.release(1)五、非可重入锁极简版对比理解 state 作用六、核心知识点总结七、常见面试考点一、AQS 核心原理回顾AQSAbstractQueuedSynchronizer核心state 同步状态volatile int state独占锁中0无锁1持有锁1重入次数CLH 双向阻塞队列竞争失败线程封装成 Node 入队自旋 / 阻塞等待前驱唤醒两种模式独占ExclusiveReentrantLock、共享ShareCountDownLatch/Semaphore自定义锁只需要继承AQS重写核心 4 个方法tryAcquire(int arg)尝试获取独占锁tryRelease(int arg)尝试释放独占锁isHeldExclusively()判断当前线程是否持有锁二、可重入独占锁完整代码仿 ReentrantLock 非公平锁javaimport java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** * 基于AQS实现 可重入独占锁 */ public class AqsReentrantLock implements Lock { // 内部同步器继承AQS private final Sync sync new Sync(); // AQS同步器实现 private static class Sync extends AbstractQueuedSynchronizer { /** * 尝试获取独占锁 * arg1加锁一次重入时state1 */ Override protected boolean tryAcquire(int arg) { int state getState(); Thread current Thread.currentThread(); // 1. 无锁直接CAS抢锁 if (state 0) { if (compareAndSetState(0, arg)) { // 设置持有锁的线程 setExclusiveOwnerThread(current); return true; } } // 2. 已持有锁可重入state累加 else if (getExclusiveOwnerThread() current) { setState(state arg); return true; } // 3. 其他线程持有锁获取失败 return false; } /** * 释放独占锁 * arg1释放一次state-1state归0才算完全释放 */ Override protected boolean tryRelease(int arg) { // 校验必须是持有锁线程才能释放 if (getExclusiveOwnerThread() ! Thread.currentThread()) { throw new IllegalMonitorStateException(当前线程未持有锁无法释放); } int newState getState() - arg; boolean fullyReleased (newState 0); // 完全释放清空持有线程 if (fullyReleased) { setExclusiveOwnerThread(null); } setState(newState); return fullyReleased; } /** 判断当前线程是否独占持有锁 */ Override protected boolean isHeldExclusively() { return getExclusiveOwnerThread() Thread.currentThread(); } // 新建条件变量Condition依赖AQS内部等待队列 Condition newCondition() { return new ConditionObject(); } } // Lock接口实现全部委托给sync Override public void lock() { // acquire内部调用tryAcquire失败则入队阻塞 sync.acquire(1); } Override public void lockInterruptibly() throws InterruptedException { // 可中断获取锁阻塞时响应中断 sync.acquireInterruptibly(1); } Override public boolean tryLock() { // 仅尝试一次不阻塞 return sync.tryAcquire(1); } Override public boolean tryLock(long time, java.util.concurrent.TimeUnit unit) throws InterruptedException { // 超时尝试获取锁 return sync.tryAcquireNanos(1, unit.toNanos(time)); } Override public void unlock() { // release调用tryRelease完全释放后唤醒后继等待线程 sync.release(1); } Override public Condition newCondition() { return sync.newCondition(); } // 辅助方法获取当前锁重入次数 public int getHoldCount() { return sync.getState(); } // 辅助方法判断当前线程是否持有锁 public boolean isLockedByCurrentThread() { return sync.isHeldExclusively(); } }三、测试代码验证重入、阻塞、Condition 等待唤醒javapublic class LockTest { public static void main(String[] args) throws InterruptedException { AqsReentrantLock lock new AqsReentrantLock(); Condition condition lock.newCondition(); // 测试1锁重入 new Thread(() - { lock.lock(); System.out.println(第一次加锁重入次数 lock.getHoldCount()); lock.lock(); System.out.println(第二次重入重入次数 lock.getHoldCount()); try { // 等待条件 System.out.println(线程等待condition); condition.await(); System.out.println(线程被唤醒继续执行); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(释放一次锁重入次数 lock.getHoldCount()); lock.unlock(); System.out.println(完全释放锁重入次数 lock.getHoldCount()); } }).start(); Thread.sleep(1000); // 测试2主线程唤醒等待线程 lock.lock(); System.out.println(主线程获取锁执行signal); condition.signal(); lock.unlock(); } }四、关键方法流程拆解1. 获取锁sync.acquire(1)javapublic final void acquire(int arg) { // 1. 先tryAcquire抢锁成功直接返回 // 2. 失败则addWaiter封装Node入CLH队列 // 3. acquireQueued自旋阻塞直到前驱释放锁唤醒自己 if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }2. 释放锁sync.release(1)javapublic final boolean release(int arg) { // 1. tryRelease扣减state返回是否完全释放(state0) if (tryRelease(arg)) { Node h head; // 2. 完全释放后唤醒CLH队列后继等待线程 if (h ! null h.waitStatus ! 0) unparkSuccessor(h); return true; } return false; }五、非可重入锁极简版对比理解 state 作用如果不需要重入tryAcquire只判断state0不判断持有线程javaOverride protected boolean tryAcquire(int arg) { if (getState() 0) { compareAndSetState(0, 1); setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } Override protected boolean tryRelease(int arg) { if (getExclusiveOwnerThread() ! Thread.currentThread()) throw new IllegalMonitorStateException(); setState(0); setExclusiveOwnerThread(null); return true; }缺点同一线程多次 lock 会永久阻塞必须保证 lock/unlock 成对一次。六、核心知识点总结state 语义自定义独占锁用 state 记录持有次数共享锁记录许可数独占线程标记exclusiveOwnerThread实现可重入、非法释放校验CLH 队列竞争失败线程阻塞前驱释放后唤醒后继保证 FIFOConditionObjectAQS 内置等待队列await()释放锁阻塞signal()移入 CLH 队列等待竞争公平 / 非公平区别非公平抢锁时不判断队列是否有等待线程直接 CAS公平锁先判断hasQueuedPredecessors()七、常见面试考点为什么 AQS 用双向链表前驱节点可以快速取消等待清理失效节点waitStatus 状态含义0 初始、-1 SIGNAL需要唤醒后继、-2 CONDITION条件等待、1 CANCELLED线程取消acquireQueued 为什么自旋避免频繁 park/unpark 内核切换轻量级自旋优化性能可重入锁依赖exclusiveOwnerThread区分持有线程state 记录重入次数