← 返回博客首页
⚡ Java并发编程面试10题 高频 ★★★★★
并发编程是Java面试最核心的模块之一——80%的后端岗位必考。这10道题覆盖2026年最高频考点,每道附答案要点+代码。
📢 本文来源:3天10+HR真实沟通中提炼的面试题库。
1. synchronized锁升级过程是怎样的?必考
答案:JDK6后synchronized引入了锁升级机制——无锁 → 偏向锁 → 轻量级锁 → 重量级锁,只升不降。
• 偏向锁:对象头标记线程ID,同一线程重入无需CAS,减少开销
• 轻量级锁:竞争时通过CAS将Mark Word指向栈中Lock Record,自旋等待
• 重量级锁:自旋失败后膨胀,依赖Monitor(ObjectMonitor),线程阻塞
面试亮点:"偏向锁延迟(Biased Locking延迟4秒)在JDK15已默认禁用——因为高并发下偏向锁撤销成本高。"
2. AQS原理是什么?ReentrantLock和CountDownLatch怎么基于AQS实现的?
答案:AQS(AbstractQueuedSynchronizer)是JUC包的核心骨架。内部维护一个
int state +
FIFO双向队列(CLH变体)。
工作流程:
获取锁:tryAcquire(state)→CAS改state→失败→入队→park阻塞
释放锁:tryRelease(state)→唤醒后续节点→unpark
• ReentrantLock:state=0未锁,state≥1已锁(可重入计数)
• CountDownLatch:state=计数器,countDown()减1,await()等待state=0
面试必答:"AQS通过模板方法模式(tryAcquire/tryRelease)让子类实现,ReentrantLock有公平/非公平两种实现。"
3. volatile底层实现原理?和synchronized区别?
答案:volatile通过
内存屏障(Memory Barrier)实现:
•
可见性:写volatile变量后插入StoreLoad屏障,强制刷新到主存
•
禁止重排序:通过happens-before规则约束
vs synchronized:
| 特性 | volatile | synchronized |
| 原子性 | ❌ 不保证 | ✅ 保证 |
| 可见性 | ✅ | ✅ |
| 性能 | 高(无锁) | 较低 |
| 适用 | 状态标记 | 临界区 |
4. 线程池核心参数怎么设置?拒绝策略有哪些?
答案:
ThreadPoolExecutor(核心线程数, 最大线程数, 空闲存活时间,
时间单位, 工作队列, 线程工厂, 拒绝策略)
•
IO密集型:核心线程 = 2 × CPU核数 + 1
•
CPU密集型:核心线程 = CPU核数 + 1
4种拒绝策略:
1. AbortPolicy(默认):抛RejectedExecutionException
2. CallerRunsPolicy:调用者线程执行
3. DiscardPolicy:直接丢弃
4. DiscardOldestPolicy:丢弃队列最老任务
5. ThreadLocal内存泄漏原因?怎么解决?
答案:ThreadLocal的Entry继承了WeakReference,但key是弱引用、value是强引用。
泄漏原因:GC回收key后,value仍被Entry强引用,且Entry被Thread→ThreadLocalMap强引用→value永不回收。
解决:①调用remove()方法(最关键);②使用静态ThreadLocal减少实例数;③JDK8已优化——ThreadLocalMap的set/get/remove会主动清理key=null的Entry。
6. CAS的ABA问题是什么?怎么解决?
答案:CAS比较时,值从A→B→A,误判为"未变"。
解决方案:
• AtomicStampedReference:加版本号(stamp),每次更新version+1
• AtomicMarkableReference:加布尔标记位,适合"是否被改过"场景
实战:"秒杀项目用Redis Lua脚本而不用CAS——Redis单线程天然避免ABA。"
7. ConcurrentHashMap在JDK7和JDK8的实现区别?
答案:从分段锁 → CAS+synchronized的演进。
• JDK7:Segment数组 + HashEntry,并发度=段数(默认16),分段锁
• JDK8:Node数组 + CAS + synchronized,锁粒度到桶级别,链表→红黑树(≥8)
为什么改?"JDK7分段锁浪费内存且锁粒度固定,JDK8用CAS+synchronized(synchronized优化后性能相当)更灵活。"
8. 死锁的四个必要条件?怎么排查?
答案:
• 互斥:资源独享
• 持有并等待:持有资源A等资源B
• 不可剥夺:别人不能用
• 循环等待:A等B、B等A
排查:①jstack PID查看死锁线程;②jconsole可视化检测;③Arthas thread -b查找死锁。
9. CompletableFuture怎么用?和Future有什么区别?
Future缺点:①get()阻塞获取;②无法链式回调;③不能组合多个异步任务。
CompletableFuture:
CompletableFuture.supplyAsync(() -> 查订单)
.thenApply(order -> 算价格)
.thenAccept(price -> System.out.println(price))
.exceptionally(e -> 默认值);
关键方法:
supplyAsync有返回值、
runAsync无返回值、
thenCombine合并两结果、
allOf等全部完成。
10. 如何设计一个秒杀系统的并发控制?
答案:分层控制——
① 前端:按钮防抖+验证码
② 网关:令牌桶限流(Sentinel)
③ 服务层:Redis Lua原子扣库存+Redisson分布式锁防重复下单
④ 异步层:RocketMQ削峰+异步落库
⑤ 数据库:乐观锁version字段+Canal监听binlog对账
面试金句:"秒杀本质是三层防护:限流→原子扣减→异步缓冲。任何一层漏了,下一层都会被打穿。"
☕ 看完有收获?请我喝杯咖啡
这份资料帮你拿Offer,赞助让我继续更新
扫码赞赏 | 更多工具:github.com/Abyte-zym