← 返回博客首页

⚡ 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:
特性volatilesynchronized
原子性❌ 不保证✅ 保证
可见性
性能高(无锁)较低
适用状态标记临界区

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对账
面试金句:"秒杀本质是三层防护:限流→原子扣减→异步缓冲。任何一层漏了,下一层都会被打穿。"

🛠 更多免费Java求职工具

📝 简历生成器 ☕ 面试题库 🎯 模拟面试 💼 接单主页