CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单

适用:Java 并发、AQS、线程同步面试;问题由浅入深,附带【标准答案】+【面试官连环追问】

基础概念类

Q1:简单说下三个工具各自作用、使用场景?

参考答案

  1. CountDownLatch:闭锁。一个 / 多个线程等待其他 N 个线程执行完成,一次性使用,不可重置。 场景:多任务并行查询、服务启动等待初始化、压测闸门。
  2. CyclicBarrier:循环栅栏。一组线程互相等待,所有人到达屏障点再继续;支持循环复用,可设置屏障回调任务。 场景:多阶段分段并行计算。
  3. Semaphore:信号量。控制同时访问资源的线程数量,实现限流、资源抢占。 场景:接口限流、连接池、有限资源调度。

面试官追问 追问 1:CountDownLatch 能不能实现循环等待?为什么? 追问 2:CyclicBarrier 的回调任务由哪个线程执行?


Q2:CountDownLatch 和 CyclicBarrier 最核心区别?

参考答案

  1. 等待关系不同
  • CountDownLatch:外部等待线程等待工作线程;等待方与执行方可以完全分离。
  • CyclicBarrier:线程之间互相等待,参与等待的是同一组线程。
  1. 复用性
  • CountDownLatch:state 归 0 后永久失效,不能重置。
  • CyclicBarrier:一轮结束自动重置,可循环使用。
  1. 回调
  • CountDownLatch:无内置回调。
  • CyclicBarrier:支持 barrierAction,凑齐线程后执行。
  1. 异常传播
  • CyclicBarrier:一个线程中断 / 超时 → 屏障破损,其余等待线程抛出BrokenBarrierException
  • CountDownLatch 单个线程异常不会连锁影响其他等待线程。

面试官追问 追问 1:如果我想要重复等待一组任务完成,选谁? 追问 2:能不能用 CountDownLatch 模拟实现 CyclicBarrier?有什么弊端?

底层原理类(面试重点)

Q3:三者底层基于什么实现?

参考答案

  1. CountDownLatch:AQS 共享模式,state 充当计数器。
  2. Semaphore:AQS 共享模式;支持公平 / 非公平两种模式。
  3. CyclicBarrier:没有直接使用 AQS ,底层 ReentrantLock + Condition,外加 Generation(代机制)实现循环与屏障破损标记。

面试官追问 追问 1:AQS 共享锁与独占锁区别? 追问 2:Semaphore 公平和非公平区别,什么时候选公平?

Q4:CountDownLatch await ()、countDown () 底层流程?

参考答案

  • await ():调用tryAcquireShared,state>0 则进入 AQS 队列阻塞;state=0 才放行。
  • countDown():releaseShared,CAS 自旋 state-1;当 state 减到 0 时唤醒所有等待线程。

面试官追问 追问:getCount () 获取的值一定准确吗?为什么不能用于业务判断?

Q5:CyclicBarrier Generation 代的作用,什么叫屏障破损?

参考答案 Generation 用来区分每一轮等待。 破损触发条件:

  1. 等待线程调用 await 被中断;
  2. await 超时抛出 TimeoutException; 屏障一旦破损,其他阻塞线程立刻收到BrokenBarrierException。调用 reset () 可以手动恢复屏障。

面试官追问 追问:屏障破损后不 reset 继续使用会发生什么?

使用踩坑 & 生产实践(高频手写题场景)

Q6:使用 CountDownLatch 有哪些坑?

参考答案

  1. countDown () 不要写在 try 内部,务必放在 finally;任务异常会导致计数不减,永久阻塞。
  2. 生产环境禁止裸 await (),优先使用带超时await(time,unit)防止死锁。
  3. 初始化 count 值要和 countDown 调用次数匹配。
  4. 不可循环复用,循环场景不要复用同一个实例。

面试官追问 追问:线程池配合 CountDownLatch 代码怎么写?

Q7:CyclicBarrier 典型坑?

参考答案

  1. 实际参与 await 的线程数 ≠ parties → 永久阻塞。
  2. barrierAction 由最后到达的线程执行,不要放超长耗时逻辑。
  3. 出现线程中断 / 超时导致屏障破损,所有等待线程抛异常。
  4. reset () 时机不对,正在等待的线程会收到异常。

面试官追问 追问:如何优雅捕获 BrokenBarrierException?

Q8:Semaphore 有哪些使用注意点?

参考答案

  1. acquire () 获取许可,release () 释放;release 不要随意调用,避免许可膨胀
  2. 最好保证 acquire 与 release 成对,建议 finally 释放。
  3. 支持 tryAcquire 非阻塞获取,避免无限阻塞。
  4. 公平信号量上下文切换开销更大,并发高场景默认非公平。

面试官追问 追问:可以一个线程多次 acquire、多次 release 吗?会出现什么问题?

场景选型题(面试官最喜欢现场辨析)

Q9:场景选择题,分别选用什么?

场景 1:调用 3 个微服务并行查询,全部返回再组装结果 → CountDownLatch 场景 2:3 组线程分阶段计算,阶段全部完成再进入下一阶段 → CyclicBarrier 场景 3:限制最多同时 20 个线程访问文件资源 → Semaphore

面试官追问 追问:如果使用 CyclicBarrier 实现并行调用多个接口行不行?有什么缺点?

灵魂深度追问(大厂常考)

Q10:Semaphore 和线程池核心参数 maximumPoolSize 限流区别?

参考答案

  • ThreadPoolExecutor:限制工作线程数量;任务队列还能堆积任务。
  • Semaphore:限制并发执行业务的数量,和线程池大小无关,可以用于跨线程池、跨应用资源限流。

Q11:CountDownLatch 与 Join 对比?

参考答案 thread.join () 只能等待指定线程;CountDownLatch 更加灵活: 可以等待任意一批线程、支持超时、线程池场景友好;join 无法设置超时(JDK 无原生超时 API)。


精简对比速查表(面试可以直接默写)

表格

特性 CountDownLatch CyclicBarrier Semaphore
核心作用 等待一批任务执行完毕 线程互相等待,统一推进 控制并发访问数量
复用 一次性,不可重置 自动循环复用 许可可反复获取释放
底层 AQS 共享锁 ReentrantLock + Condition AQS 共享锁
回调 支持屏障回调
计数器 单向递减 每轮自动重置 可增可减(许可)
典型异常 InterruptedException BrokenBarrierException、TimeoutException InterruptedException

附赠面试一句话背诵模板

  1. CountDownLatch:一个线程等 N 个线程,一次性门闩
  2. CyclicBarrier:N 个线程互相等,集合完毕再出发,支持多轮
  3. Semaphore:通行证,控制同一时刻多少线程能进入资源

相关推荐
我命由我123454 小时前
CesiumJS 笔记 - 获取容器中心点、Cartesian3 clone 方法、修改 Cartesian3 对象的高度
前端·javascript·css·前端框架·html·html5·js
Hopebearer_5 小时前
页面突然只剩 DOM?一次静态资源版本错配排查
前端·部署
东风破_6 小时前
ESLint 是什么?为什么你的项目需要它?
前端·后端·代码规范
圣殿骑士-Khtangc7 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
ShineWinsu7 小时前
对于C++:C++11中lambda、function、bind的解析
c++·面试·笔试·开发·lambda·bind·function
码匠许师傅7 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
BigTopOne8 小时前
【ijkplayer】 硬解码流程
前端
kyriewen8 小时前
DeepSeek Harness开源第一天我就上手了——和Claude Code的差距比想象中大
前端·ai编程·deepseek
捡田螺的小男孩9 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员
sakiko_9 小时前
OC学习笔记-面试题
面试·objective-c