Java AQS 是什么?它如何实现线程排队、阻塞和唤醒?
下面是一段教学用的模拟面试。
🧑💻 面试官:ReentrantLock 底层为什么会用到 AQS?
🙋♂️ 我:AQS 有一个队列,抢不到锁的线程就在里面排队。
🧑💻 面试官:那前一个线程释放锁,队首线程是不是就直接拿到锁了?
🙋♂️ 我:应该会被唤醒,然后拿到锁。
🧑💻 面试官:被唤醒和拿到锁是一回事吗?既然有 FIFO 队列,为什么 ReentrantLock 还分公平和非公平?
这道题要把两件事分开:「等到机会」和「获取成功」。队列组织等待,状态和获取规则决定谁能进入。
面试速答(60 秒版)
AQS 是 Java 用来构建锁、信号量等同步器的基础框架。它主要管理一个整型状态和等待队列,让获取失败的线程能够等待,并在资源释放后重新尝试。
但是,状态代表什么、怎样才算获取成功,需要具体同步器来定义。例如 ReentrantLock 用状态记录重入次数,Semaphore 用它表示剩余许可。
获取失败的线程可能进入队列并被阻塞;前面的线程释放资源后,等待线程被唤醒,再次检查能不能获取。唤醒不是把锁直接交给它。
同时,FIFO 队列也不等于默认公平。获取时是否允许新来的线程插队,要看同步器的策略。实际项目中通常使用成熟同步器,不会为了“底层用 AQS”就自己实现一把锁。

知识点详解:AQS 怎样把资源状态和等待线程组织起来
先弄清楚 state 在记录什么
咱们假设两个线程都要修改同一份订单数据,需要先拿到一把 ReentrantLock。
没有线程持有锁时,状态可以理解为 0。T1 获取成功以后,状态变成 1,同时记录锁的持有者。如果 T1 再次获取同一把锁,状态继续增加,这就是重入。它也需要释放相同次数,状态回到 0 时,其他线程才有机会进入。
这里的 0、1 不是 AQS 强制规定的所有含义,而是这把锁的实现规则。如果换成 Semaphore,状态又可以表示剩余许可数量。因此,AQS 管理状态,但不替所有同步器定义状态的业务含义。
状态更新需要原子操作,避免两个线程同时看见空闲、同时宣布自己获取成功。不过,只会 CAS 还不够:总有线程获取失败,系统还得安排它怎样等。
获取失败以后,线程怎样等到下一次机会?
继续看 T1、T2。
T1 已经持有锁,T2 来获取。获取规则发现 T2 不是持有者,锁也没有空闲,因此这次失败。AQS 会把等待组织到同步队列中;等待过程中可能先做有限重试,然后在适当条件下通过 park 暂停线程,不需要一直占着 CPU 空转。
T1 释放锁后,如果锁已经完全释放,框架会安排唤醒等待线程。T2 从等待中回来以后,仍要重新执行获取逻辑。成功了才往下走;不成功就继续等待。
为什么还要检查?因为唤醒只代表“你可以再试了”。线程真正得到运行机会之前,资源状态可能已经变化;等待也不能依赖“每次醒来一定满足条件”这样的假设。
公平锁会在获取规则里考虑前面有没有等待者,尽量按等待顺序获取。非公平锁则允许新来的线程在某些时机先尝试。因此,AQS 官方 API 特别区分了队列顺序和获取策略,不能看到 FIFO 就推导出公平。

独占与共享,区别在于允许几个人进入
ReentrantLock 是独占同步的例子。同一时刻只有一个线程持有这把锁,但这个持有者可以重入。
Semaphore 可以作为共享同步的例子。假设只有两个许可,每个任务获取一个,那么两个任务可以一起运行,第三个需要等待。任务释放许可以后,后面的任务再尝试获取。
共享模式并不表示“所有线程都能同时进入”,也不等于一定读共享数据。它表示获取规则可以允许多个获取者同时满足条件。许可数量、一次申请几个许可,仍由同步器定义。

面试官继续追问
有了 CAS,为什么还需要等待队列?
CAS 解决一次状态修改能否成功,不负责组织长期竞争。如果所有失败线程一直重试,会浪费 CPU。队列与阻塞让失败线程能够等待,并把释放后的重试机会组织起来。
被唤醒的线程还是获取失败,会丢失唤醒吗?
不能把“收到一次唤醒”当作成功凭证。正确的同步框架会围绕状态检查、入队、阻塞和重试处理竞争,使用者也不能在自己的等待代码里省略条件检查。
公平锁一定更好吗?
公平更关注等待顺序,非公平可能减少交接带来的开销。要结合吞吐量、等待时间分布和是否能接受长期等待来判断,而不是只比较一次执行速度。
面试速记卡
- AQS:管理同步状态、等待队列和等待重试的基础框架。
- state:具体含义由同步器定义,不是所有场景都代表锁次数。
- 获取失败:可以排队、阻塞,资源释放后再尝试。
- 唤醒:恢复尝试的机会,不代表已经获取成功。
- 公平:由获取策略保证,不能从 FIFO 队列直接推导。
- 独占与共享:看获取规则允许多少获取者同时满足条件。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
阿里巴巴 · Java后端 · 社招
ReentrantLock 怎样通过 AQS 实现公平、可重入和可中断锁?(题意整理)
社招一年半面经分享 · 阿里部分 ↗
历史面经,面试年份未明确;页面编辑于 2024-07-19