Java 并发常见问题总结

Java 并发常见问题总结(高频面试八股 + 真实生产问题全集)

这是一篇系统性、面试+生产双导向的 Java 并发问题总结,几乎覆盖了 90% 的并发面试题和线上事故根源。建议结合之前的基础篇(并发三性、JMM、Happens-Before、线程生命周期)一起复习。

一、基础概念类问题

  1. 并发与并行的区别?
  • 并发:同一时间段内多个任务交替执行(单核也能并发)。
  • 并行:同一时刻多个任务同时执行(依赖多核CPU)。
  1. 并发编程的三大核心问题是什么?
  • 原子性可见性有序性
  1. Java内存模型(JMM)解决了什么问题?
  • 屏蔽各种硬件和操作系统的内存访问差异,保证并发程序在不同平台下能得到一致的执行结果。
  1. Happens-Before 原则有哪些?(至少能说出前6条)
  • 程序次序规则、监视器锁规则、volatile变量规则、传递性、线程启动规则、线程终止规则、线程中断规则、对象终结规则。

二、线程相关高频问题

  1. start() 和 run() 的区别?
  • start():启动新线程,进入RUNNABLE状态,由JVM调用run()。
  • run():普通方法调用,在当前线程执行,无新线程创建。
  1. 线程有哪几种状态?状态是如何转换的?
  • NEW → RUNNABLE → BLOCKED / WAITING / TIMED_WAITING → TERMINATED。
  1. 线程的创建方式有哪些?哪种最好?
  • 继承Thread、实现Runnable、实现Callable+FutureTask、线程池(推荐)
  1. 守护线程和用户线程的区别?
  • 守护线程:为主线程服务,JVM退出时自动结束(setDaemon(true)必须在start前)。
  • 用户线程:普通线程,JVM退出需等待所有用户线程结束。

三、线程安全与锁机制问题

  1. 什么情况下会出现线程不安全?
  • 多个线程同时读写共享变量,且至少有一个写操作,且没有正确同步。
  1. synchronized 的底层原理?
    • 基于对象头中的Mark Word实现锁。
    • 锁升级过程:偏向锁 → 轻量级锁(自旋) → 重量级锁(Monitor)。
  2. synchronized 和 ReentrantLock 的区别?(超级高频)
维度synchronizedReentrantLock
实现方式JVM内置(Monitor)JDK API(AQS)
可重入
公平锁不支持支持(可传入true)
锁获取方式自动获取/释放手动 lock() + unlock()(需try-finally)
等待可中断不支持支持(lockInterruptibly)
超时获取锁不支持支持(tryLock(timeout))
条件等待仅支持一个Condition支持多个Condition
性能JDK1.6后优化后接近更灵活,但代码稍复杂
  1. volatile 的作用?能保证原子性吗?
    • 保证可见性 + 有序性(禁止指令重排序)。
    • 不能保证原子性(i++ 仍非原子)。
  2. CAS 的原理?有什么缺点?
    • Compare And Swap(乐观锁)。
    • ABA 问题、无限循环(自旋开销)、只能保证单个变量原子性。

四、生产中最常见的并发问题

  1. 死锁(经典事故)
    • 四个必要条件:互斥、请求并持有、不可剥夺、循环等待。
    • 如何避免:固定加锁顺序、tryLock超时、资源一次性分配。
    • 如何排查:jstack、jconsole、arthas thread -b。
  2. 活锁
    • 线程不断尝试但始终无法推进(例如两个线程互相谦让)。
  3. 线程饥饿
    • 低优先级线程长期得不到CPU时间。
  4. 上下文切换开销过大
    • 线程数远大于CPU核数时,频繁切换导致性能急剧下降。
    • 经验:CPU密集型线程数 ≈ CPU核数;IO密集型 ≈ CPU核数 × 2~4。
  5. ThreadLocal 内存泄漏
    • 原因:ThreadLocalMap 的 key 是弱引用,value 是强引用。
    • 解决:使用完后手动 remove(),或在线程池中特别注意。
  6. 线程池参数设置不当导致的问题
    • 核心线程数、最大线程数、队列容量、拒绝策略设置错误。
    • 常见事故:队列用无界LinkedBlockingQueue,导致OOM。
  7. 并发容器使用错误
    • 迭代时修改(ConcurrentModificationException)。
    • HashMap 在高并发下死循环(JDK7扩容时)。
    • 应该使用 ConcurrentHashMap、CopyOnWriteArrayList 等。

五、并发工具类问题

  1. CountDownLatch vs CyclicBarrier vs Semaphore
    • CountDownLatch:一次性倒计时(不可重用)。
    • CyclicBarrier:可重用栅栏,所有线程到达后再一起通过。
    • Semaphore:限流(控制同时访问资源的线程数)。
  2. Future / CompletableFuture 的使用场景?
  3. AQS(AbstractQueuedSynchronizer)是什么?
    • ReentrantLock、Semaphore、CountDownLatch 等工具类的底层框架。
    • 核心是 state + CLH 等待队列。

六、生产调优与排查经验

  • 线上CPU 100%:arthas thread、jstack 找热点线程。
  • 频繁 Full GC:ThreadLocal 未 remove、大量对象创建在线程池中。
  • 响应时间突增:锁竞争严重、线程池队列积压。
  • 死锁/活锁:arthas dashboard + thread -b。

七、并发问题总结口诀(便于背诵)

三性不保出事故,死锁活锁饥饿堵;
volatile见序不原子,synchronized锁升级;
ReentrantLock更灵活,AQS统一做底层;
线程池参数要慎设,ThreadLocal记得remove;
并发容器用Concurrent,迭代修改要小心。


推荐复习顺序

  1. 并发基础(三性、JMM、Happens-Before)
  2. 线程与线程池
  3. synchronized + volatile + CAS
  4. AQS + ReentrantLock
  5. 并发工具类(JUC)
  6. 并发容器 + ThreadLocal
  7. 生产问题排查(arthas/jstack)

想深入哪一块?我可以立刻给你展开完整一篇:

  • 「synchronized 锁升级全过程 + 源码」
  • 「AQS 原理与 ReentrantLock 实现」
  • 「线程池 7 大参数 + 源码执行流程」
  • 「CompletableFuture 异步编程实战」
  • 「生产中遇到的 10 个经典并发事故复盘」

直接回复对应标题或“下一节 AQS”,我马上给你最详细的版本。

并发是Java进阶的分水岭,学透了这些,你就真正具备了写高并发系统的能力!继续加油!

文章已创建 5130

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部