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:通行证,控制同一时刻多少线程能进入资源

相关推荐
qetfw3 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具
甲维斯3 小时前
我要开始吹牛逼了!Kimi K3 “宇宙无敌”!
前端·人工智能
a1117763 小时前
微光小屋-前端养成小游戏 开源项目
前端
kyriewen3 小时前
我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
前端·javascript·ai编程
张鑫旭3 小时前
快速过下我2026年上半年的前端学了些啥
前端
এ慕ོ冬℘゜3 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
hoLzwEge4 小时前
拯救低效调试!code-inspector-plugin 让代码定位如虎添翼
前端·前端框架·node.js