【Java并发编程】锁机制:AQS抽象队列同步器:核心原理、CLH队列、独占/共享模式、基于AQS实现的组件(CountDownLatch、CyclicBarrier等)(附《思维导图》+《面试高频考点清单》)

简介: AQS(AbstractQueuedSynchronizer)是Java并发包(JUC)的基石框架,基于volatile state状态变量与CLH双向等待队列,通过模板方法模式支持独占/共享同步语义,为ReentrantLock、Semaphore、CountDownLatch等核心组件提供统一底层实现。

思维导图

image.png

Java并发编程:AQS抽象队列同步器 系统性知识体系

一、AQS概述与核心定位

AbstractQueuedSynchronizer(抽象队列同步器)是Java并发包java.util.concurrent.locks基石,由Doug Lea设计。它提供了一个基于FIFO等待队列的同步器框架,用于实现依赖于原子状态的锁和同步器。

1.1 核心设计思想

  • 状态驱动:用一个volatile int state变量表示同步状态
  • 队列管理:内置双向链表实现的CLH变种队列管理等待线程
  • 模板方法模式:AQS实现了同步队列的核心逻辑,子类通过重写protected方法定义具体的同步语义
  • 两种模式:支持独占模式(Exclusive)和共享模式(Shared)

1.2 AQS在JUC中的地位

几乎所有JUC同步工具都直接或间接基于AQS实现:

  • 锁:ReentrantLockReentrantReadWriteLock
  • 同步器:CountDownLatchCyclicBarrierSemaphoreExchanger
  • 异步任务:FutureTaskThreadPoolExecutor中的Worker

二、AQS核心数据结构

2.1 同步状态state

private volatile int state;
  • 核心变量:表示锁的持有状态或同步资源数量
  • volatile修饰:保证多线程间的可见性
  • 操作方法
    • getState():原子获取当前状态
    • setState(int newState):原子设置状态
    • compareAndSetState(int expect, int update):CAS原子更新状态

2.2 等待节点Node

构成CLH队列的基本单元,每个等待线程被封装为一个Node节点:

属性 类型 说明
waitStatus int 节点等待状态
prev Node 前驱节点
next Node 后继节点
thread Thread 当前节点对应的线程
nextWaiter Node 条件队列中的下一个节点

waitStatus枚举值

  • SIGNAL(-1):后继节点需要被当前节点唤醒
  • CANCELLED(1):节点已取消(超时或中断)
  • CONDITION(-2):节点在条件队列中等待
  • PROPAGATE(-3):共享模式下需要传播唤醒
  • 0:初始状态

2.3 CLH同步队列

AQS使用双向链表实现的CLH变种队列:

  • head:头节点(哑节点,不代表实际等待线程)
  • tail:尾节点,指向队列最后一个等待节点
  • 特点:FIFO、无锁入队(CAS实现)、高效的节点管理

三、CLH队列核心机制

3.1 CLH队列的由来

原始CLH锁是Craig、Landin、Hagersten发明的自旋锁,AQS对其进行了改造:

  • 将自旋改为阻塞+唤醒机制
  • 从单向链表改为双向链表
  • 增加了取消、条件等待等高级功能

3.2 入队操作

当线程获取锁失败时,会被封装成Node节点加入队列尾部:

  1. 创建新节点,设置thread为当前线程
  2. CAS设置tail为新节点(保证原子性)
  3. 将原tail节点的next指向新节点

3.3 出队操作

当锁被释放时,会唤醒头节点的后继节点:

  1. 被唤醒的线程尝试获取锁
  2. 获取成功后,将自己设置为新的head节点
  3. 原head节点的next置为null,帮助GC回收

3.4 节点取消

当线程等待超时或被中断时,节点会被标记为CANCELLED

  1. 将节点的waitStatus设置为CANCELLED
  2. 调整前驱和后继节点的指针,将取消节点从队列中移除
  3. 唤醒后继节点(如果需要)

四、独占模式(Exclusive)

独占模式下,同一时刻只能有一个线程持有锁。典型实现:ReentrantLock

4.1 获取锁流程

public final void acquire(int arg) {
   
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

详细步骤

  1. 尝试获取锁:调用tryAcquire(arg)(子类实现)
  2. 入队:获取失败,调用addWaiter(Node.EXCLUSIVE)创建独占节点并加入队列
  3. 队列中等待:调用acquireQueued(node, arg)在队列中自旋等待
    • 检查前驱节点是否是head节点
    • 如果是,再次尝试获取锁
    • 成功则设置为新head,返回
    • 失败则检查是否需要阻塞
    • 需要则调用LockSupport.park()阻塞线程
    • 被唤醒后继续循环
  4. 处理中断:如果等待过程中被中断,调用selfInterrupt()设置中断标志

4.2 释放锁流程

public final boolean release(int arg) {
   
    if (tryRelease(arg)) {
   
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

详细步骤

  1. 尝试释放锁:调用tryRelease(arg)(子类实现)
  2. 唤醒后继:释放成功,调用unparkSuccessor(head)唤醒head节点的后继节点
  3. 后继节点被唤醒后,继续在acquireQueued中尝试获取锁

4.3 可中断与超时获取

  • 可中断获取acquireInterruptibly(int arg)
    • 在阻塞过程中可以响应中断
    • 抛出InterruptedException
  • 超时获取tryAcquireNanos(int arg, long nanosTimeout)
    • 在指定时间内尝试获取锁
    • 超时返回false

五、共享模式(Shared)

共享模式下,多个线程可以同时持有锁。典型实现:SemaphoreCountDownLatchReentrantReadWriteLock的读锁。

5.1 获取锁流程

public final void acquireShared(int arg) {
   
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}

详细步骤

  1. 尝试获取共享锁:调用tryAcquireShared(arg)(子类实现)
    • 返回值<0:获取失败
    • 返回值=0:获取成功,但没有剩余许可
    • 返回值>0:获取成功,还有剩余许可
  2. 入队等待:获取失败,调用doAcquireShared(arg)将线程加入队列并自旋等待
  3. 传播唤醒:获取成功后,调用setHeadAndPropagate(node, r)设置新head并传播唤醒后续共享节点

5.2 释放锁流程

public final boolean releaseShared(int arg) {
   
    if (tryReleaseShared(arg)) {
   
        doReleaseShared();
        return true;
    }
    return false;
}

详细步骤

  1. 尝试释放共享锁:调用tryReleaseShared(arg)(子类实现)
  2. 传播释放:释放成功,调用doReleaseShared()唤醒后继节点
  3. 后继节点被唤醒后,继续尝试获取共享锁

5.3 传播唤醒机制

共享模式的核心特点是传播唤醒

  • 当一个共享线程获取锁后,如果还有剩余许可,会继续唤醒下一个共享节点
  • 这保证了所有等待的共享线程都能被及时唤醒
  • setHeadAndPropagatedoReleaseShared两个方法共同实现

六、条件变量Condition

Condition接口替代了Object的wait/notify机制,提供了更精确的线程等待/唤醒控制。一个Lock可以对应多个Condition

6.1 ConditionObject实现

AQS的内部类ConditionObject实现了Condition接口:

  • 维护一个单向条件队列
  • 条件队列与同步队列相互独立
  • 线程调用await()时会从同步队列转移到条件队列
  • 线程调用signal()时会从条件队列转移回同步队列

6.2 await()流程

  1. 将当前线程封装成Node节点加入条件队列
  2. 释放当前持有的锁
  3. 阻塞线程,等待被唤醒
  4. 被唤醒后,重新获取锁
  5. 返回并继续执行

6.3 signal()/signalAll()流程

  • signal():将条件队列中的第一个节点转移到同步队列,并唤醒该线程
  • signalAll():将条件队列中的所有节点转移到同步队列,并依次唤醒

七、基于AQS实现的核心组件

7.1 ReentrantLock(可重入锁)

  • 模式:独占模式
  • 特点:可重入、支持公平/非公平模式
  • state含义:表示锁的重入次数(0表示未锁定)
  • 公平与非公平区别
    • 非公平:直接CAS尝试获取锁,失败再入队(默认)
    • 公平:先检查队列是否有等待线程,有则直接入队

7.2 ReentrantReadWriteLock(读写锁)

  • 模式:读锁(共享)+ 写锁(独占)
  • state含义:高16位表示读锁数量,低16位表示写锁数量
  • 特性
    • 写锁可以降级为读锁
    • 读锁不能升级为写锁
    • 写锁与读锁互斥,读锁之间共享

7.3 CountDownLatch(倒计时门闩)

  • 模式:共享模式
  • 用途:一个线程等待多个线程完成
  • state含义:表示需要等待的线程数量
  • 核心方法
    • countDown():将计数减1
    • await():等待计数变为0

7.4 CyclicBarrier(循环屏障)

  • 实现:基于ReentrantLockCondition
  • 用途:多个线程互相等待,直到所有线程都到达屏障点
  • 特点:可以循环使用,支持屏障动作
  • 与CountDownLatch区别
    • CountDownLatch是一次性的,CyclicBarrier可以循环使用
    • CountDownLatch是一个线程等待多个线程,CyclicBarrier是多个线程互相等待

7.5 Semaphore(信号量)

  • 模式:共享模式
  • 用途:控制同时访问资源的线程数量
  • state含义:表示可用的许可数量
  • 核心方法
    • acquire():获取一个许可
    • release():释放一个许可

7.6 FutureTask(异步任务)

  • 模式:独占模式
  • 用途:表示异步计算的结果
  • state含义:表示任务的执行状态(NEW、COMPLETING、NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTED)
  • 核心方法
    • get():等待计算完成并获取结果
    • cancel():取消任务

八、AQS设计思想与性能分析

8.1 核心设计思想

  1. 模板方法模式:将不变的队列管理逻辑封装在AQS中,可变的同步语义留给子类实现
  2. 自旋+阻塞:先自旋尝试获取锁,失败再阻塞,减少上下文切换
  3. CAS操作:使用CAS实现无锁队列操作,避免重量级锁的开销
  4. 双向链表:高效的节点插入和删除操作,支持节点取消
  5. 分层唤醒:精确控制线程的唤醒时机,避免不必要的唤醒

8.2 性能优势

  • 高并发:通过CAS和volatile实现无锁操作,减少竞争
  • 低延迟:自旋机制减少了线程阻塞和唤醒的次数
  • 可扩展性:可以方便地实现各种自定义同步器
  • 公平性支持:可以选择公平或非公平模式

8.3 局限性

  • 单一状态变量:只能有一个同步状态变量,对于复杂的同步语义可能不够
  • 不支持优先级:队列是FIFO的,不支持线程优先级调度
  • 不可重入的独占锁:AQS本身不直接支持不可重入的独占锁(需要子类实现)

九、自定义AQS同步器

9.1 必须重写的方法

根据同步模式,需要重写以下方法之一:

  • 独占模式tryAcquire(int arg)tryRelease(int arg)
  • 共享模式tryAcquireShared(int arg)tryReleaseShared(int arg)

9.2 示例:简单的不可重入独占锁

public class SimpleLock extends AbstractQueuedSynchronizer {
   
    @Override
    protected boolean tryAcquire(int arg) {
   
        return compareAndSetState(0, 1);
    }

    @Override
    protected boolean tryRelease(int arg) {
   
        setState(0);
        return true;
    }

    public void lock() {
   
        acquire(1);
    }

    public void unlock() {
   
        release(1);
    }
}

十、常见面试问题与实战要点

10.1 高频面试问题

  1. AQS的核心原理是什么?
  2. CLH队列的工作原理是什么?
  3. 独占模式和共享模式的区别是什么?
  4. ReentrantLock的公平锁和非公平锁实现有什么区别?
  5. CountDownLatch和CyclicBarrier的区别是什么?
  6. AQS中的waitStatus有哪些值,分别代表什么?
  7. Condition的实现原理是什么?
  8. AQS为什么使用双向链表而不是单向链表?
  9. AQS中的head节点为什么是哑节点?
  10. 如何基于AQS实现一个自定义同步器?

10.2 实战最佳实践

  1. 优先使用JDK提供的同步组件,不要重复造轮子
  2. 合理选择公平锁和非公平锁(非公平锁性能更好)
  3. 始终在finally块中释放锁,避免死锁
  4. 使用Condition实现精确的线程等待/唤醒
  5. 注意锁的粒度,避免长时间持有锁
  6. 对于读多写少的场景,优先使用读写锁

Java并发编程-AQS抽象队列同步器 面试高频考点清单

说明:本清单按照面试考察频率分级(★★★★★ 必考,★★★★ 高频,★★★ 中频),每个考点提炼核心答案要点,适合突击复习和背诵。所有内容均来自JDK 8源码标准实现。


一、基础概念与核心定位(★★★★★)

考点 核心答案要点
1. AQS是什么?核心设计思想 定义:Doug Lea设计的java.util.concurrent.locks基石,基于FIFO队列的同步器框架
四大核心思想
① 状态驱动:volatile int state表示同步状态
② 队列管理:CLH变种双向队列管理等待线程
③ 模板方法:AQS实现队列逻辑,子类重写protected方法定义语义
④ 双模式:支持独占/共享两种同步模式
2. AQS在JUC中的地位 几乎所有JUC同步工具都直接/间接基于AQS实现:
• 锁:ReentrantLockReentrantReadWriteLock
• 同步器:CountDownLatchCyclicBarrierSemaphore
• 异步:FutureTaskThreadPoolExecutor.Worker

二、核心数据结构(★★★★★)

考点 核心答案要点
1. 同步状态state • 核心变量:表示锁持有状态或同步资源数量
volatile修饰:保证多线程可见性
• 原子操作:getState()setState()compareAndSetState()
2. Node节点核心属性 waitStatus:节点等待状态
prev/next:双向链表前驱/后继指针
thread:当前节点封装的线程
nextWaiter:条件队列中的下一个节点
3. waitStatus5个枚举值 SIGNAL(-1):后继节点需要被当前节点唤醒
CANCELLED(1):节点已取消(超时/中断)
CONDITION(-2):节点在条件队列中
PROPAGATE(-3):共享模式下需要传播唤醒
0:初始状态
4. CLH同步队列结构 • 双向链表实现的FIFO队列
head哑节点(不代表实际等待线程)
tail:队列尾节点
• 无锁入队:通过CAS设置tail保证原子性

三、CLH队列核心机制(★★★★★)

考点 核心答案要点
1. AQS对原始CLH锁的改造 原始CLH是自旋锁(单向链表),AQS改造为:
① 自旋→阻塞+唤醒机制
② 单向链表→双向链表
③ 增加节点取消、条件等待等高级功能
2. 入队流程(获取锁失败) ① 创建Node.EXCLUSIVE/SHARED节点
② CAS自旋设置tail为新节点
③ 将原tail的next指向新节点
3. 出队流程(锁释放后) ① 唤醒head节点的后继节点
② 被唤醒线程尝试获取锁
③ 获取成功后将自己设为新head
④ 原head的next置null帮助GC
4. 节点取消流程 触发条件:线程等待超时或被中断
① 将节点waitStatus设为CANCELLED
② 调整前后指针,将取消节点从队列移除
③ 唤醒后继节点(如果需要)
5. 为什么用双向链表? • 支持O(1)时间复杂度删除任意节点(如取消节点)
• 单向链表只能从头遍历,删除中间节点需要O(n)时间
6. head为什么是哑节点? • 简化队列操作逻辑,避免频繁判断head是否为null
• 统一处理第一个等待节点和后续节点的唤醒流程

四、独占模式(Exclusive)(★★★★★)

同一时刻只能有一个线程持有锁,典型实现:ReentrantLock

考点 核心答案要点
1. acquire()完整流程(源码级)
acquireQueued细节
• 只有前驱是head时才尝试获取锁
• 失败则调用LockSupport.park()阻塞
• 被唤醒后继续循环
public final void acquire(int arg) {
   
  if (!tryAcquire(arg) && // 1. 子类尝试获取锁
      acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 2. 入队+自旋等待
      selfInterrupt(); // 3. 处理中断
}
考点 核心答案要点
2. release()完整流程(源码级)
public final boolean release(int arg) {
   
  if (tryRelease(arg)) {
    // 1. 子类尝试释放锁
    Node h=head;
    if (h!=null && h.waitStatus!=0)
      unparkSuccessor(h); // 2. 唤醒head后继
    return true;
  }
  return false;
}
考点 核心答案要点
3. 可中断与超时获取 acquireInterruptibly():阻塞时响应中断,抛出InterruptedException
tryAcquireNanos(long):指定时间内获取失败返回false

五、共享模式(Shared)(★★★★)

多个线程可同时持有锁,典型实现:SemaphoreCountDownLatch、读锁

考点 核心答案要点
1. tryAcquireShared返回值含义 <0:获取失败
=0:获取成功,但无剩余许可
>0:获取成功,还有剩余许可
2. 传播唤醒机制 核心特点:一个共享线程获取锁后,若还有剩余许可,会继续唤醒后续共享节点
实现:由setHeadAndPropagate()doReleaseShared()共同完成
目的:保证所有等待的共享线程都能被及时唤醒
考点 核心答案要点
3. 独占vs共享模式核心区别
对比维度 独占模式 共享模式
同一时刻持有线程数 1个 多个
典型实现 ReentrantLock、写锁 Semaphore、CountDownLatch、读锁
核心方法 acquire()/release() acquireShared()/releaseShared()
唤醒机制 只唤醒一个后继 传播唤醒多个后继

六、条件变量Condition(★★★★)

替代Object.wait/notify,支持一个Lock对应多个Condition,实现精确唤醒

考点 核心答案要点
1. Condition vs Object.wait/notify • 一个Lock可对应多个Condition,实现分组唤醒
• 支持可中断等待超时等待
• 避免了notifyAll()导致的"惊群效应"
2. await()流程 ① 将线程封装为Node加入条件队列(单向)
② 释放当前持有的锁
③ 调用LockSupport.park()阻塞
④ 被唤醒后转移到同步队列
⑤ 重新获取锁后返回
3. signal()vssignalAll() signal():将条件队列第一个节点转移到同步队列并唤醒
signalAll():将条件队列所有节点转移到同步队列并依次唤醒

七、基于AQS实现的核心组件(★★★★★)

7.1 ReentrantLock(可重入锁)

  • 模式:独占模式
  • state含义:锁的重入次数(0表示未锁定)
  • 公平vs非公平
    • 非公平(默认):直接CAS尝试获取锁,失败再入队
    • 公平:先检查队列是否有等待线程,有则直接入队

7.2 ReentrantReadWriteLock(读写锁)

  • 模式:读锁(共享)+ 写锁(独占)
  • state划分:高16位=读锁数量,低16位=写锁数量
  • 特性:写锁可降级为读锁,读锁不可升级为写锁

7.3 CountDownLatch vs CyclicBarrier(必考对比)

对比维度 CountDownLatch CyclicBarrier
实现原理 直接基于AQS共享模式 基于ReentrantLock+Condition
用途 一个线程等待多个线程完成 多个线程互相等待到屏障点
state含义 需要等待的线程数量 还需到达屏障的线程数
可复用性 一次性(计数到0后无法重置) 可循环使用(reset()方法)
异常处理 不支持 支持屏障动作和异常处理

7.4 Semaphore(信号量)

  • 模式:共享模式
  • state含义:可用许可数量
  • 用途:控制同时访问资源的最大线程数

7.5 FutureTask(异步任务)

  • 模式:独占模式
  • state含义:任务执行状态(NEW→COMPLETING→NORMAL/EXCEPTIONAL)
  • 核心get()方法阻塞等待任务完成

八、设计思想与性能分析(★★★)

考点 核心答案要点
1. 核心设计模式 模板方法模式:封装不变的队列逻辑,子类实现可变的同步语义
享元模式:Node节点复用线程对象
观察者模式:节点等待前驱节点唤醒
2. 性能优势 • 高并发:CAS+volatile实现无锁队列操作
• 低延迟:先自旋后阻塞,减少上下文切换
• 可扩展性:轻松实现自定义同步器
3. 局限性 • 只有一个state变量,复杂同步语义需要额外变量
• 队列是FIFO,不支持线程优先级调度
• 不直接支持不可重入独占锁(需子类实现)

九、自定义AQS同步器(★★★)

考点 核心答案要点
1. 必须重写的方法 • 独占模式:tryAcquire(int)tryRelease(int)
• 共享模式:tryAcquireShared(int)tryReleaseShared(int)
2. 简单不可重入独占锁示例
public class SimpleLock extends AbstractQueuedSynchronizer {
   
  @Override
  protected boolean tryAcquire(int arg) {
   
    return compareAndSetState(0, 1);
  }
  @Override
  protected boolean tryRelease(int arg) {
   
    setState(0);
    return true;
  }
  public void lock() {
    acquire(1); }
  public void unlock() {
    release(1); }
}

十、面试答题技巧与实战易错点(★★★★)

10.1 面试答题通用思路

回答AQS问题时遵循"总-分-例"结构:

  1. 总述:一句话说明核心概念
  2. 分点:按核心组件/流程分点阐述(突出关键词)
  3. 举例:结合JDK中的具体实现说明

10.2 实战易错点

  • 必须在finally块中释放锁,否则会导致死锁
  • 非公平锁性能优于公平锁(默认使用非公平)
  • Condition.await()必须在持有锁的情况下调用
  • 读多写少场景优先使用ReentrantReadWriteLock

终极必背10题(覆盖90%以上AQS面试题)

  1. 简述AQS的核心原理和设计思想
  2. 详细说明AQS的CLH队列结构和工作机制
  3. 独占模式下acquire()release()的执行流程
  4. 共享模式的传播唤醒机制是什么?为什么需要?
  5. ReentrantLock的公平锁和非公平锁实现有什么区别?
  6. CountDownLatch和CyclicBarrier的区别是什么?
  7. AQS中的waitStatus有哪些值?分别代表什么?
  8. Condition的实现原理是什么?与Object.wait/notify有什么区别?
  9. AQS为什么使用双向链表?head节点为什么是哑节点?
  10. 如何基于AQS实现一个自定义同步器?

Java并发-AQS 一页纸速记版

考前3分钟突击专用 | 只保留必考核心关键词高频对比表格 | 覆盖90%以上AQS面试题


一、核心定位(★★★★★)

  • AQS:JUC锁机制基石,Doug Lea设计
  • 四大核心思想volatile state驱动 + CLH双向队列 + 模板方法 + 独占/共享双模式
  • JUC全家桶:ReentrantLock、读写锁、CountDownLatch、CyclicBarrier、Semaphore、FutureTask

二、核心数据结构(★★★★★)

1. 同步状态state

  • volatile int:锁状态/资源数量
  • 原子操作:getState()setState()compareAndSetState()

2. Node节点waitStatus(必背)

含义
-1 SIGNAL:后继需要被唤醒
1 CANCELLED:节点已取消
-2 CONDITION:在条件队列
-3 PROPAGATE:共享模式传播
0 初始状态

3. CLH队列

  • 双向链表FIFO
  • head:哑节点(不存实际线程)
  • tail:队列尾节点(CAS入队)

三、CLH核心机制(★★★★★)

  • 入队:创建Node → CAS设tail → 原tail.next指向新节点
  • 出队:唤醒head后继 → 获取锁 → 设为新head → 原head置空
  • 为什么双向链表:O(1)删除取消节点
  • 为什么哑节点:简化队列操作逻辑

四、独占vs共享模式(★★★★★)

维度 独占模式 共享模式
同时持有线程 1个 多个
核心方法 acquire()/release() acquireShared()/releaseShared()
唤醒机制 只唤醒1个后继 传播唤醒多个后继
典型实现 ReentrantLock、写锁 Semaphore、CountDownLatch、读锁

独占模式核心流程

tryAcquire() → 失败→addWaiter()acquireQueued()(自旋+阻塞)→ 中断则selfInterrupt()

共享模式核心

  • tryAcquireShared()返回值:<0失败,=0成功无剩余,>0成功有剩余
  • 传播唤醒:有剩余许可则继续唤醒后续共享节点

五、Condition条件变量(★★★★)

  • 替代Object.wait/notify,一个Lock对应多个Condition
  • await()流程:加入条件队列 → 释放锁 → 阻塞 → 转移到同步队列 → 重新获取锁
  • signal():转移条件队列第一个节点到同步队列
  • 优势:分组精确唤醒,避免惊群效应

六、基于AQS的核心组件(★★★★★)

1. ReentrantLock

  • 独占模式,state=重入次数
  • 非公平(默认):直接CAS抢锁 → 失败入队
  • 公平:先检查队列是否有等待 → 有则直接入队

2. 读写锁(ReentrantReadWriteLock)

  • 读锁(共享)+ 写锁(独占)
  • state:高16位=读锁数,低16位=写锁数
  • 特性:写锁可降级,读锁不可升级

3. CountDownLatch vs CyclicBarrier(必考对比)

维度 CountDownLatch CyclicBarrier
实现 直接基于AQS共享 基于Lock+Condition
用途 一个线程等多个 多个线程互相等
可复用 一次性 可循环(reset())

4. Semaphore

  • 共享模式,state=可用许可数
  • 用途:控制并发访问上限

七、终极必背10题(考前默念)

  1. AQS核心原理和设计思想
  2. CLH队列结构和工作机制
  3. 独占模式acquire()/release()流程
  4. 共享模式传播唤醒机制
  5. ReentrantLock公平vs非公平实现
  6. CountDownLatch vs CyclicBarrier
  7. AQS的5个waitStatus含义
  8. Condition实现原理和优势
  9. 为什么用双向链表?为什么head是哑节点?
  10. 如何基于AQS实现自定义同步器

使用说明

  1. 考前快速扫一遍加粗关键词所有表格
  2. 重点记忆带★★★★★的必考内容
  3. 终极必背10题能脱口而出,AQS面试基本稳了
相关文章
|
8天前
|
人工智能 开发工具 iOS开发
Claude Code 新手完全上手指南:安装、国产模型配置与常用命令全解
Claude Code 是一款运行在终端环境中的 AI 编程助手,能够直接在命令行中完成代码生成、项目分析、文件修改、命令执行、Git 管理等开发全流程工作。它最大的特点是**任务驱动、终端原生、轻量高效、多模型兼容**,无需图形界面、不依赖 IDE 插件,能够深度融入开发者日常工作流。
3000 7
|
11天前
|
Shell API 开发工具
Claude Code 快速上手指南(新手友好版)
AI编程工具卷疯啦!Claude Code凭借任务驱动+终端原生的特性,成了开发者的效率搭子。本文从安装、登录、切换国产模型到常用命令,手把手带新手快速上手,全程避坑,30分钟独立用起来。
3091 20
|
23天前
|
人工智能 JSON 供应链
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
LucianaiB分享零成本畅用JVS Claw教程(学生认证享7个月使用权),并开源GeoMind项目——将JVS改造为科研与产业地理情报可视化AI助手,支持飞书文档解析、地理编码与腾讯地图可视化,助力产业关系图谱构建。
23568 15
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
|
4天前
|
人工智能 Linux BI
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
JeecgBoot AI专题研究 一键脚本:Claude Code + JeecgBoot Skills + DeepSeek 全平台接入 一行命令装好 Claude Code + JeecgBoot Skills + DeepSeek 接入,无需翻墙使用 Claude Code,支持 Wind
1979 3
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
|
10天前
|
人工智能 JSON BI
DeepSeek V4-Pro 接入 Claude Code 完全实战:体验、测试与关键避坑指南
Claude Code 作为当前主流的 AI 编程辅助工具,凭借强大的代码理解、工程执行与自动化能力深受开发者喜爱,但原生模型的使用成本相对较高。为了在保持能力的同时进一步降低开销,不少开发者开始寻找兼容度高、价格更友好的替代模型。DeepSeek V4 系列的发布带来了新的选择,该系列包含 V4-Pro 与 V4-Flash 两款模型,并提供了与 Anthropic 完全兼容的 API 接口,理论上只需简单修改配置,即可让 Claude Code 无缝切换为 DeepSeek 引擎。
2495 3
|
9天前
|
人工智能 安全 开发工具
Claude Code 官方工作原理与使用指南
Claude Code 不是传统代码补全工具,而是 Anthropic 推出的终端 AI 代理,具备代理循环、双驱动架构(模型+工具)、全局项目感知、6 种权限模式等核心能力,本文基于官方文档系统解析其工作原理与高效使用技巧。
1364 0
|
9天前
|
存储 Linux iOS开发
【2026最新】MarkText中文版Markdown编辑器使用图解(附安装包)
MarkText是一款免费开源、跨平台的Markdown编辑器,主打所见即所得实时预览,支持Windows/macOS/Linux。内置数学公式、流程图、代码高亮、多主题及PDF/HTML导出,是Typora的轻量免费替代首选。(239字)