知识点专题话题 #7

Java 并发面试题:锁、线程池与可见性

面试之星官方的头像 面试之星官方 更新于

通过可复现的并发例子理解正确性,再讨论吞吐与资源边界。

适用范围

内存模型参考 Java SE 21 语言规范;线程池 API 请核对项目 JDK。

并发面试的起点是共享状态与业务不变量。先确认多个线程怎样读写同一份数据,再判断原子性、可见性和顺序约束。只有正确性边界清晰后,吞吐和延迟比较才有意义。

学习顺序

  1. 识别共享状态。 用计数器的复合更新说明为什么一次业务操作可能对应多次读取和写入。
  2. 建立同步关系。 阅读 happens-before 规则,用加锁、线程启动与结束等具体例子解释观察到的结果。
  3. 选择并发工具。 比较锁、原子变量与并发容器能提供的保证。容器内部安全不代表容器上的业务组合自动安全。
  4. 管理任务与资源。 画出线程池提交、入队、执行、拒绝的路径,并讨论超时、取消和关闭。

练习:下游接口变慢

设定一个有并发请求的服务:下游耗时突然上升,线程和队列逐步被占满。列出需要监测的队列长度、活动线程、等待时间和拒绝次数;为不同任务类型设计处理策略。

追问方向

线程数需要依据任务等待时间、CPU 使用、下游容量和压测结果评估,不能只套公式。讨论无界队列时,说明积压如何转化为内存风险;讨论拒绝策略时,说明业务是否允许丢弃或重试。

复盘时记录一次错误假设,以及证明它错误的最小程序。

参考资料

相关学习路线

安排复习节奏

30 天 Java 面试计划

Java 并发题库

共 74 道题

按题库默认顺序排列,可选择分类集中练习。

显示 74 道题

  1. Java 线程和操作系统的线程有啥区别? 线程基础
  2. 多线程会产生哪些并发(线程不安全)问题 内存模型与可见性
  3. Java 创建线程有几种方法 线程基础
  4. Runnable 和 Callable 有什么区别? 线程基础
  5. 为什么使用 start 启动线程,而不使用 run 方法启动线程 线程基础
  6. Java 中获取线程返回值有几种方法 异步任务与结果
  7. Java 线程有哪些状态(生命周期) 线程基础
  8. Thread.sleep 和 Object.wait 的区别 线程基础
  9. Thread.sleep() 有什么用?sleep(0) 有什么用? 线程基础
  10. 什么是守护线程?守护线程的底层原理 线程基础
  11. Java 是怎么加锁的,有哪些锁?分别在哪些场景使用? 锁与同步
  12. 介绍下 Java 内存模型(JMM) 内存模型与可见性
  13. 如何保证原子性 内存模型与可见性
  14. 介绍下 long 和 double 的非原子性协定 内存模型与可见性
  15. 自增和自减操作是原子的吗 内存模型与可见性
  16. 如何保证可见性 内存模型与可见性
  17. 如何保证有序性(Happens-before) 内存模型与可见性
  18. synchronized 的使用方法 锁与同步
  19. synchronized 原理 锁与同步
  20. synchronized 可以锁空对象吗 锁与同步
  21. 为什么把 JDK 1.6 之前的 synchronized 称为重量级锁 锁与同步
  22. synchronized 锁升级过程(轻量级锁、偏向锁) 锁与同步
  23. 知道逃逸分析吗(锁消除、栈上分配、标量替换) 锁与同步
  24. 什么是 synchronized 锁粗化 锁与同步
  25. 为什么 wait/notify/notifyAll 方法必须在 synchronized 同步块中调用(无效唤醒) 锁与同步
  26. 什么是虚假唤醒 锁与同步
  27. volatile 的作用、原理 内存模型与可见性
  28. 内存屏障是什么?它是怎么干涉排序的? 内存模型与可见性
  29. synchronized 和 volatile 的区别 内存模型与可见性
  30. final 的作用、原理 内存模型与可见性
  31. 什么是 CAS?CAS 原理?CAS 存在的三大问题 CAS 与原子类
  32. Java 中有哪些地方实现用到了 CAS CAS 与原子类
  33. Atomic 原子类有了解吗 CAS 与原子类
  34. 为什么有了 synchronized 还需要 Lock 接口?各自的适用场景是什么 锁与同步
  35. 讲讲你对 AQS 的理解(AQS、Condition 底层原理) 锁与同步
  36. 介绍下 ReentrantLock 的底层原理(可重入的原理、公平锁和非公平锁的原理) 锁与同步
  37. 什么是读写锁(ReadWriteLock),怎么实现,什么时候用读写锁? 锁与同步
  38. Java 里面有什么机制可以唤醒阻塞线程(LockSupport) 锁与同步
  39. 知道哪些线程安全的 List(Vector,CopyOnWriteArrayList) 并发容器与队列
  40. 知道哪些阻塞队列(BlockingQueue)?底层原理是什么 并发容器与队列
  41. 介绍 ArrayBlockingQueue 和 LinkedBlockingQueue 的底层区别,高并发情况下哪个表现更好 并发容器与队列
  42. 介绍 SynchronousQueue 及其底层原理 并发容器与队列
  43. 延时队列(DelayQueue)底层原理 并发容器与队列
  44. 知道哪些线程安全的 Map(synchronizedMap,Hashtable,ConcurrentHashMap)?ConcurrentHashMap 原理 并发容器与队列
  45. 介绍 CountDownLatch 的底层原理及其适用场景 并发协作工具
  46. 介绍 CyclicBarrier 的底层原理及其适用场景,和 CountDownLatch 有什么不同 并发协作工具
  47. 介绍 Semaphore 的底层原理及其适用场景 并发协作工具
  48. 介绍 Exchanger 的底层原理及其适用场景 并发协作工具
  49. 介绍 ThreadLocal 原理,以及使用的时候的注意事项(Threadlocal 内存泄漏) ThreadLocal 与上下文
  50. ThreadLocal 父子线程之间如何传递数据 ThreadLocal 与上下文
  51. 如果一个线程想要使用其他线程的信息,该怎么做 ThreadLocal 与上下文
  52. 什么是线程池?为什么要用线程池? 线程池
  53. 线程池中存在线程复用的情况,如何在线程之间传递上下文信息?(TransmittableThreadLocal) 线程池
  54. 线程池的状态有哪些(线程池的生命周期) 线程池
  55. 线程池的工作原理 线程池
  56. 线程池为什么要先判断阻塞队列是否已满,再判断线程数是否小于最大线程数,而不是反过来呢 线程池
  57. 线程池的四种饱和策略(拒绝策略) 线程池
  58. 如果线程池中的线程数量已经到达 maximumPoolSize,但是仍然有新任务来临,并且该任务的优先级比较高,不允许直接丢弃,希望该任务立即执行,该如何处理 线程池
  59. 线程池的创建方法?为什么不要使用 Executors 创建线程池 线程池
  60. 创建线程时需要区分核心线程和非核心线程吗? 线程池
  61. 创建线程池时的基本参数?如何合理配置这些参数 线程池
  62. 两种提交任务方法(submit 和 execute)的区别 线程池
  63. 线程池中的线程是如何被回收的?核心线程如何实现保活? 线程池
  64. 线程池中的某个线程异常了,那么线程池会怎么处理这个线程? 线程池
  65. 如何监控线程池的运行状态 线程池
  66. 如何判断线程池的任务是否都执行完了 线程池
  67. 主线程启动多个子线程,需要等待多个子线程完成后拿到执行结果,才能继续执行,Java 中如何实现?(CompletableFuture) 异步任务与结果
  68. CompletableFuture 原理 异步任务与结果
  69. Java 线程的通信(同步)方式有哪些 锁与同步
  70. 怎么统计 Java 线程的阻塞时间和运行时间 线程基础
  71. 多线程手写题:按序打印 多线程编程练习
  72. 多线程手写题:三个线程 T1、T2、T3,如何让他们(循环)按序打印 ABC 多线程编程练习
  73. 多线程手写题:两线程交替打印奇偶数 多线程编程练习
  74. 多线程手写题:写一个死锁 多线程编程练习

评论 0 友善交流,让每个问题都有回响

还没有评论,分享你的看法吧。