并发设计模式与线程安全实践

共 99 题
📑 题目列表 99 题
#
★★★

1. 双重检查锁定(Double-Checked Locking)在 Java 5+ 的 volatile 正确实现,与静态内部类懒加载的取舍

双重检查锁定(Double-Checked Locking)在 Java 5+ 的 volatile 正确实现是什么?与静态内部类懒加载的取舍是什么?

  • DCL volatile 实现
  • 静态内部类懒加载
  • 取舍

DCL 正确实现:单例字段 volatile,第一次无锁检查,加锁后第二次检查,构造后 volatile 安全发布(防半初始化)。静态内部类懒加载:利用 JVM 类加载机制,静态内部类(Holder)在首次访问时才加载初始化单例,天然线程安全、无 DCL 复杂度。取舍:DCL 需 volatile 与细心,但可延迟初始化且性能好;静态内部类更简单、无锁、懒加载,是推荐方式。DCL 适合需要手动控制或已用 volatile 的场景,静态内部类更简洁。

DCL 用 volatile 保安全,静态内部类靠类加载机制保安全。静态内部类更推荐(简单无锁)。

#
★★★

2. 读写锁(ReadWriteLock)在读多写少场景下的锁降级,与乐观锁在校验上的差异

读写锁(ReadWriteLock)在读多写少场景下的锁降级,与乐观锁在校验上的差异是什么?

  • 锁降级
  • 乐观锁校验
  • 差异

读写锁锁降级:持有写锁时再取读锁,然后释放写锁,保持读一致(用于缓存更新后读一致性)。乐观锁校验:读时不加锁,写时校验版本(CAS/validate),失败重试。差异:读写锁是悲观锁(读有锁、写互斥),乐观锁是乐观(读无锁、写校验)。锁降级保证"一致读",乐观锁保证"写前校验"。读多写少:读写锁降级确保读一致,乐观锁(StampedLock 乐观读)读无锁更高吞吐。选择:需严格一致读用锁降级,可重试用乐观锁。

锁降级(悲观)保证一致读,乐观锁(写校验)读无锁。高读低写用乐观锁更优。

#
★★★

3. Copy-on-Write 模式在配置快照与路由表更新中的应用,与读锁方案的取舍

Copy-on-Write 模式在配置快照与路由表更新中的应用,与读锁方案的取舍是什么?

  • Copy-on-Write
  • 配置快照
  • 读锁方案

Copy-on-Write:写时复制整个配置/路由表,用 volatile/AtomicReference 引用替换,读无锁(读快照)。应用:配置快照、路由表更新(读多写少,写时替换)。与读锁方案取舍:读锁方案(ReentrantReadWriteLock)读有锁(原子计数),并发读有争用;Copy-on-Write 读无锁(快照),读吞吐高,但写 O(n) 复制、内存开销大。取舍:读多写少、写频率低用 Copy-on-Write;写频繁或数据大用读锁。Copy-on-Write 适合配置/路由这类低频更新。

Copy-on-Write 读无锁快照、写复制,适合低频更新读取出众。读锁适合写频繁。

#
★★★

4. Guarded Suspension 模式的条件队列实现,为什么等待必须放在 while 循环中

Guarded Suspension 模式的条件队列实现:为什么等待必须放在 while 循环中?

  • Guarded Suspension
  • 条件队列
  • while 循环

Guarded Suspension 模式:线程在条件不满足时挂起,条件满足时唤醒。用条件队列(wait/notify 或 Condition)实现。等待必须放 while 循环的原因:1) 虚假唤醒(wait 可能无通知返回);2) 条件被其他线程抢先改变(唤醒后条件又不满足)。while 循环保证"唤醒后重新检查条件,不满足继续等待",避免"条件不满足却消费"的错误。这是 Guarded Suspension 的正确性核心。

while 循环防虚假唤醒与条件抢先改变,是 Guarded Suspension 的规范写法。

#
★★★

5. Future 模式的轮询与回调,FutureTask 状态机在任务编排中的边界

Future 模式的轮询与回调:FutureTask 状态机在任务编排中的边界是什么?

  • Future 轮询
  • 回调
  • FutureTask 状态机

Future 模式:轮询(isDone 轮询)或阻塞(get)获取结果。回调:用 CompletableFuture 的完成回调。FutureTask 状态机:NEW→COMPLETING→NORMAL/EXCEPTIONAL/CANCELLED/INTERRUPTED,用 CAS 状态转换保证完成/取消/中断的确定性。边界:FutureTask 状态机适合"单任务完成/取消"的确定性管理;但无回调、无组合,编排复杂任务需 CompletableFuture。Future 的边界是"单任务结果获取",组合/回调超出其范围。

FutureTask 状态机管单任务完成/取消,编排需 CompletableFuture。边界是单任务。

#
★★★

6. 线程封闭(Thread Confinement)的三种形式与逃逸风险

线程封闭(Thread Confinement)的三种形式与逃逸风险是什么?

  • 线程封闭
  • 三种形式
  • 逃逸风险

线程封闭:保证对象只被一个线程访问,无需同步。三种形式:1) 栈封闭(局部变量,只在方法内);2) ThreadLocal 封闭(每线程一份);3) 对象封装(封装在单线程运行的对象内)。逃逸风险:对象被其他线程访问(如局部变量被发布、ThreadLocal 值被共享、this 逃逸)则封闭失效,需同步。线程封闭是"无同步的最佳实践",但要防逃逸(别把封闭对象传给其他线程)。

线程封闭三种形式(栈/ThreadLocal/封装),防逃逸是关键,逃逸则需同步。

#
★★★

7. 不可变对象(Immutable Object)的三个线程安全条件与构建策略

不可变对象(Immutable Object)的三个线程安全条件与构建策略是什么?

  • 不可变对象
  • 三个条件
  • 构建策略

不可变对象线程安全三条件:1) 所有字段 final;2) 状态不可变(无 setter,不可修改);3) 安全发布(构造完成后不逃逸,this 不泄露)。构建策略:1) 字段 final + 防修改;2) 构造器内完成所有初始化;3) 用静态工厂 + 防御性拷贝;4) 避免可变对象引用外泄。不可变对象天然线程安全(final 安全发布),适合共享。构建时防 this 逃逸与可变字段。

三条件:final、不可变、安全发布。不可变对象天然安全,构建避免可变字段与逃逸。

#
★★★

8. 单例模式在多线程环境下的安全发布,饿汉/懒汉/DCL/枚举的并发语义

单例模式在多线程环境下的安全发布:饿汉/懒汉/DCL/枚举的并发语义是什么?

  • 饿汉
  • 懒汉/DCL
  • 枚举单例

单例并发语义:饿汉(静态初始化)由类加载保证线程安全,但非懒加载;懒汉(直接 getInstance)需 synchronized 或 DCL+volatile;DCL(volatile+双重检查)懒加载+线程安全;枚举单例(enum)由 JVM 保证单实例+线程安全+防序列化,是推荐。安全发布:饿汉/静态内部类靠类加载,DCL 靠 volatile,枚举靠 JVM。选择:枚举单例最安全简单,DCL 适合需手动控制,饿汉适合简单。

枚举单例 JVM 保证安全,DCL 需 volatile,饿汉类加载安全。枚举最推荐。

#
★★★

9. 生产者-消费者模式中队列的选择,有界队列的背压与无界队列的 OOM 风险

生产者-消费者模式中队列的选择:有界队列的背压与无界队列的 OOM 风险是什么?

  • 有界队列背压
  • 无界队列 OOM
  • 选择

有界队列:队满时生产者阻塞/拒绝,形成背压,防止积压,但需处理阻塞与超时。无界队列:生产者不阻塞,但任务无限堆积,内存占用增长,可能 OOM。选择:需背压、防积压用有界队列 + 拒绝策略;无界队列仅适于任务量可控、消费能力足够。生产-消费应匹配,有界队列保内存安全,无界队列有 OOM 风险。推荐有界队列。

有界队列背压防 OOM,无界队列积压易 OOM。生产-消费匹配,推荐有界。

#
★★★

10. Actor 模型(Akka)与共享内存并发在 Java 后端的取舍

Actor 模型(Akka)与共享内存并发在 Java 后端的取舍是什么?

  • Actor 模型
  • 共享内存并发
  • 取舍

Actor 模型(Akka):每个 Actor 封装状态+消息处理,无共享可变状态,通过消息传递通信,天然隔离、无锁、易扩展(分布式)。共享内存并发:Java 传统多线程共享对象,用锁/原子同步,性能高但脆弱(死锁、竞态)。取舍:Actor 适合高并发、分布式、状态隔离、易错业务(消息驱动);共享内存适合单机高性能、需要共享的状态、简单场景。Java 后端共享内存更常用,Actor 用于高并发隔离或分布式。选择:复杂度与可扩展性权衡。

Actor 消息隔离无锁可扩展,共享内存高性能但脆弱。按并发复杂度与扩展需求选。

#
★★★

11. Disruptor 环形缓冲区相对阻塞队列的性能优势来源(缓存行填充/无锁 CAS/预分配)

Disruptor 环形缓冲区相对阻塞队列的性能优势来源(缓存行填充/无锁 CAS/预分配)是什么?

  • 缓存行填充
  • 无锁 CAS
  • 预分配

Disruptor 相对阻塞队列的性能优势:1) 缓存行填充(@Contended):Sequence 独立缓存行,避免伪共享;2) 无锁 CAS:无锁更新 Sequence/槽位,无阻塞竞争;3) 预分配:环形数组预分配事件对象,避免 GC 分配;4) 单生产者单消费者优化:极低竞争。对比阻塞队列(有锁、动态分配、缓存行竞争),Disruptor 在核心路径上移除锁、GC、伪共享,吞吐极高。适合超低延迟事件传递。

Disruptor 优势三来源:缓存行填充、无锁 CAS、预分配。消除锁/GC/伪共享。

#
★★★

12. Future 模式的阻塞 get、轮询 isDone 与 CompletableFuture 回调三种消费方式的取舍

Future 模式的阻塞 get、轮询 isDone 与 CompletableFuture 回调三种消费方式的取舍是什么?

  • 阻塞 get
  • 轮询 isDone
  • 回调

三种消费方式:1) 阻塞 get:简单但阻塞线程,不适合并发编排;2) 轮询 isDone:非阻塞但空转 CPU、延迟高;3) CompletableFuture 回调:完成即回调,非阻塞、高效、可编排。取舍:简单场景用 get(可接受阻塞);避免轮询(浪费);回调最优(完成驱动、可组合)。需要超时/取消用 get(timeout),需要非阻塞编排用回调。现代推荐 CompletableFuture 回调。

阻塞 get 简单但占线程,轮询浪费,回调最优。异步编排用回调。

#
★★★

13. Guarded Suspension 模式与 Balking 模式在并发状态机中的工程取舍

Guarded Suspension 模式与 Balking 模式在并发状态机中的工程取舍是什么?

  • Guarded Suspension
  • Balking
  • 取舍

Guarded Suspension:条件不满足时挂起等待,条件满足时继续(等待语义)。Balking:条件不满足时直接返回/放弃(不等待,快速失败)。取舍:Guarded Suspension 适合"必须等待条件"(如队列空等生产);Balking 适合"条件不满足就放弃"(如初始化未完成直接返回)。状态机中:Guarded Suspension 处理"等待状态转移",Balking 处理"状态未就绪则跳过"。工程选择:需等待用 Guarded Suspension,可放弃用 Balking。

Guarded Suspension 等待、Balking 放弃。按"是否必须等待条件"选择。

#
★★★

14. 阻塞队列与信号量组合的限流模式,任务提交前的准入控制

阻塞队列与信号量组合的限流模式:任务提交前的准入控制是什么?

  • 阻塞队列
  • 信号量
  • 准入控制

阻塞队列 + 信号量组合限流:信号量在任务提交前准入(acquire 通过才提交),阻塞队列承载任务。准入控制:信号量许可限制"允许进入的任务数",超许可不提交(阻塞/拒绝),防止任务无限提交;队列缓存已准入任务。组合:信号量是"入口闸门",队列是"缓冲",双限控制。比单一队列更严的准入控制,防止任务堆积。可用于削峰、防下游打爆。

信号量准入 + 队列缓冲,双限控制。任务提交前先 acquire 准入。

#
★★★

15. 线程安全发布的 happens-before 保证,final 字段与安全发布

线程安全发布的 happens-before 保证:final 字段与安全发布是什么?

  • 安全发布
  • final 字段
  • happens-before

安全发布:对象被其他线程安全读写,保证读到完整状态。happens-before 保证:1) final 字段:构造完成后读取看到最终值(构造器冻结语义,无锁);2) volatile/锁/原子:建立 happens-before(发布写→获取读);3) 静态初始化:类加载保证。final 字段提供无锁的安全发布,其他靠同步建立 happens-before。安全发布方式:静态初始化、volatile、AtomicReference、final、锁保护。核心是"发布者写与获取者读之间建立 happens-before"。

安全发布靠 happens-before 或 final 冻结。final 无锁安全,其他靠同步。

#
★★★

16. 锁分段(Striped Lock)在热点资源上的应用,与单一全局锁的对比

锁分段(Striped Lock)在热点资源上的应用,与单一全局锁的对比是什么?

  • 锁分段
  • 全局锁
  • 对比

锁分段(Striped Lock):把资源分成多段,每段独立锁,操作只锁对应段,并发度 = 段数。全局锁:单一锁保护所有资源,并发度低(互斥)。对比:锁分段提高并发度、减少竞争,适合热点资源(不同 key 不同段);全局锁简单但并发瓶颈。场景:ConcurrentHashMap 早期分段锁、缓存分片。代价:需哈希定位段、实现复杂。热点资源用锁分段提升并发。

锁分段把并发分散到多段,全局锁单点。热点资源用分段提高并发。

#
★★★

17. Worker Thread 模式与线程池的任务队列选择(有界/无界/同步队列)对背压的影响

Worker Thread 模式与线程池的任务队列选择(有界/无界/同步队列)对背压的影响是什么?

  • Worker Thread
  • 队列选择
  • 背压

Worker Thread 模式:工作线程从队列取任务执行。队列选择影响背压:有界队列(队满阻塞/拒绝,背压)、无界队列(不阻塞,无背压,OOM 风险)、同步队列(无缓冲,直接交接,强背压)。背压影响:有界/同步队列在超限时拒绝/阻塞,形成背压,防积压;无界队列无背压,积压隐患。Worker Thread + 有界队列 + 拒绝策略是"背压"的推荐组合。选择按背压需求。

队列类型决定背压:有界/同步背压,无界无背压。Worker Thread 用有界队列保背压。

#
★★★

18. 并发状态机的实现,状态字段的原子更新与版本号校验

并发状态机的实现:状态字段的原子更新与版本号校验是什么?

  • 状态机
  • 原子更新
  • 版本号校验

并发状态机:状态字段用原子更新(AtomicInteger/AtomicReference)保证状态转移原子,或用版本号校验。实现:1) 状态用 AtomicInteger,CAS 状态转移(合法转移才 CAS);2) 状态+版本号打包(AtomicStampedReference/AtomicLong),CAS 时校验版本,防 ABA;3) 非法转移拒绝。版本号校验:状态改变时版本递增,CAS 检测版本变化,确保状态一致。并发状态机保证"状态转移原子 + 合法转移唯一"。

原子状态 + CAS 转移 + 版本号防 ABA,实现并发状态机的一致转移。

#
★★★

19. 不可变对象(Immutable Object)实现线程安全的三个条件与 final 字段的内存语义配合

不可变对象(Immutable Object)实现线程安全的三个条件与 final 字段的内存语义配合是什么?

  • 不可变三条件
  • final 内存语义
  • 配合

不可变对象三条件:final 字段、不可变状态、安全发布。final 内存语义配合:final 字段构造后冻结,其他线程读到最终值(无锁可见),与"安全发布"配合实现线程安全。final 字段的冻结语义保证"构造完成后该字段即最终值",无需 volatile/锁。配合:final 保证字段值安全,不可变保证状态稳定,安全发布保证对象完整。三者配合使不可变对象天然线程安全。

final 冻结语义 + 不可变 + 安全发布,三者配合实现不可变对象的线程安全。

#
★★★

20. ConcurrentHashMap 的分段思想在自定义缓存分片中的应用

ConcurrentHashMap 的分段思想在自定义缓存分片中的应用是什么?

  • 分段思想
  • 缓存分片
  • 应用

ConcurrentHashMap 的分段思想(JDK 8 桶级 CAS + 同步)用于自定义缓存分片:把缓存按 key 哈希分到多个分片(Segment/桶),每个分片独立锁/CAS,操作只锁对应分片,提高并发。应用:1) 分片缓存(key 哈希到分片,分片内用锁/无锁);2) 分片计数器(LongAdder 的 Cell);3) 分片锁(Striped Lock)。核心:热点分散到分片,减少全局竞争。自定义缓存分片用哈希定位 + 分片锁,提升并发。

分段思想 = 哈希分散热点 + 分片锁。缓存分片提升并发,减少全局竞争。

#
★★

21. 不可变集合(List.of/Map.of)与防御性拷贝在安全发布中的协作

不可变集合(List.of/Map.of)与防御性拷贝在安全发布中的协作是什么?

  • 不可变集合
  • 防御性拷贝
  • 安全发布

不可变集合(List.of/Map.of)创建不可变集合,字段 final 后安全发布(无锁可见)。防御性拷贝:构造时拷贝传入的可变集合,防止外部修改;getter 返回拷贝,防止内部被修改。协作:构造器用防御性拷贝把可变数据转成不可变集合,存入 final 字段,安全发布;对外返回不可变集合或拷贝。这样既防外部修改(防御性拷贝),又保证线程安全(不可变+final 发布)。适合配置、快照等共享数据。

防御性拷贝防外部修改,不可变集合+final 安全发布。协作实现线程安全共享。

#
★★

22. 安全发布的五种方式(静态初始化/volatile/AtomicReference/final/锁保护)与 this 引用逃逸防范

安全发布的五种方式(静态初始化/volatile/AtomicReference/final/锁保护)与 this 引用逃逸防范是什么?

  • 五种安全发布
  • this 逃逸
  • 防范

安全发布五种方式:1) 静态初始化(类加载保证);2) volatile(写后可见);3) AtomicReference(CAS 发布);4) final 字段(构造冻结);5) 锁保护(synchronized 建立 happens-before)。this 逃逸防范:构造器内不要把 this 发布给其他线程(注册监听器、启动线程、传 this),否则其他线程看到未构造完整的对象,安全发布失效。防范:构造完成后再发布,避免 this 泄露。

五种安全发布方式建立 happens-before 或冻结。this 逃逸破坏安全发布,须防范。

#
★★

23. 并发设计模式中的 Check-Then-Act 竞态与原子化替代

并发设计模式中的 Check-Then-Act 竞态与原子化替代是什么?

  • Check-Then-Act
  • 竞态
  • 原子化替代

Check-Then-Act 竞态:先检查(check)再操作(act),两步非原子,并发下可能被其他线程插入,导致状态不一致(如检查"不存在"后插入,但线程已插入)。原子化替代:1) 用原子操作(CAS/putIfAbsent)合并检查与操作;2) 用锁包裹检查与操作;3) 用原子集合方法(putIfAbsent、computeIfAbsent)。核心是把"检查-操作"变成原子操作,消除竞态窗口。

Check-Then-Act 竞态源于检查与操作分离。用 CAS/putIfAbsent/锁原子化。

#
★★

24. 工作窃取(Work-Stealing)与任务拆分粒度的关系

工作窃取(Work-Stealing)与任务拆分粒度的关系是什么?

  • 工作窃取
  • 任务粒度
  • 关系

工作窃取依赖任务可拆分:任务拆成子任务(粒度),worker 从其他队列窃取。拆分粒度关系:粒度太细(任务多、执行短)→ 窃取频繁、调度开销大;粒度太粗(任务少、执行长)→ 负载不均、worker 空闲。理想粒度:任务执行时间适中,使窃取均衡且开销可控。工作窃取在"粒度适中的大量任务"下效率最高。拆分粒度影响窃取次数与负载均衡。

任务粒度影响窃取效率:太细开销大、太粗不均。适中粒度窃取最优。

#
★★

25. 线程封闭的三种形式(栈封闭/ThreadLocal/对象封装)的适用场景与内存泄漏代价

线程封闭的三种形式(栈封闭/ThreadLocal/对象封装)的适用场景与内存泄漏代价是什么?

  • 栈封闭
  • ThreadLocal
  • 对象封装

线程封闭三种形式:1) 栈封闭(局部变量):方法内,无泄漏,最安全;2) ThreadLocal:每线程一份,适合上下文,但线程池复用下需 remove 否则内存泄漏;3) 对象封装(单线程对象内):封装在单线程内。内存泄漏代价:ThreadLocal 最易泄漏(线程池复用,弱引用 key + 强引用 value),需 remove;栈封闭无泄漏;对象封装需确保不逃逸。场景:栈封闭本地临时、ThreadLocal 上下文、封装单线程逻辑。

三种封闭形式,ThreadLocal 有泄漏代价需 remove,栈封闭最安全。

#
★★

26. 读写锁的公平与非公平选择在吞吐与饥饿间的权衡

读写锁的公平与非公平选择在吞吐与饥饿间的权衡是什么?

  • 读写锁公平
  • 非公平
  • 吞吐/饥饿

读写锁公平(公平锁):按 FIFO 排队,避免写饥饿(读多时写也能轮到),但吞吐略低。非公平:新线程可插队,吞吐高,但读多可能饿死写(写拿不到锁)。权衡:公平锁保证无饥饿、延迟稳定,吞吐略低;非公平吞吐高但写可能饥饿。读多写少且写延迟敏感用公平锁;追求吞吐、允许写饥饿用非公平。写饥饿是 ReadWriteLock 的常见问题,公平策略缓解。

公平锁防写饥饿、吞吐略低,非公平吞吐高、写可能饥饿。按写延迟敏感度选。

#
★★

27. Balking 模式与状态检查,对象状态未就绪时直接返回的适用场景

Balking 模式与状态检查:对象状态未就绪时直接返回的适用场景是什么?

  • Balking 模式
  • 状态检查
  • 适用场景

Balking 模式:状态未就绪时直接返回(不等待、不阻塞),快速失败。适用场景:1) 初始化未完成时调用方法直接返回/抛异常;2) 任务已终止时拒绝新操作;3) 状态不对时跳过(如缓存未加载直接返回)。特点:不阻塞、不做无用功,适合"状态未就绪可安全跳过"的场景。与 Guarded Suspension 相反(等待 vs 放弃)。用于状态机、单例、资源池。

Balking 状态未就绪直接返回,适合可跳过场景。不等待、快速失败。

#
★★

28. 锁粗化与锁消除的边界,JIT 何时能优化同步代码,业务侧应如何写锁

锁粗化与锁消除的边界:JIT 何时能优化同步代码?业务侧应如何写锁?

  • 锁粗化
  • 锁消除
  • 业务写锁

锁消除:JIT 经逃逸分析证明锁对象不逃逸时删除同步。锁粗化:JIT 合并相邻的多次加锁/解锁。边界:JIT 优化依赖逃逸分析与场景,synchronized 可被优化,ReentrantLock 不可。业务侧写锁:1) 优先用 synchronized(可被 JIT 优化);2) 锁粒度适中(不因可能被消除而故意写无意义锁);3) 避免过度细锁(否则锁粗化合并);4) 不依赖锁消除(写正确锁,优化是额外收益)。业务写锁以正确性为先,优化是 JIT 的额外收益。

JIT 优化(消除/粗化)只对 synchronized,业务写正确锁、粒度适中,优化是额外收益。

#
★★

29. 线程安全的延迟初始化,holder class idiom 与 DCL 的对比

线程安全的延迟初始化:holder class idiom 与 DCL 的对比是什么?

  • holder class
  • DCL
  • 对比

holder class idiom:静态内部类持有单例,首次访问时类加载初始化,JVM 保证线程安全,无锁、简单。DCL:volatile 字段 + 双重检查,延迟初始化,需 volatile 防半初始化。对比:holder class 更简单(无锁、无 volatile、靠类加载)、推荐;DCL 需 volatile 与细心,但可手动控制。两者都延迟初始化且线程安全。holder class 是更优的延迟初始化方式。

holder class 靠类加载线程安全、简单,DCL 需 volatile。holder class 更推荐。

#
★★

30. 生产者-消费者中条件变量(Condition)的精确唤醒与信号丢失

生产者-消费者中条件变量(Condition)的精确唤醒与信号丢失是什么?

  • Condition 精确唤醒
  • 信号丢失
  • 生产者-消费者

Condition 精确唤醒:每个条件独立队列(notFull/notEmpty),signal 只唤醒对应条件,避免惊群。信号丢失:1) 若在条件改变前 signal 且无等待者,唤醒丢失(需先改条件再 signal 或 while 重查);2) notify 唤醒错误线程(一个条件被唤醒错过)。防信号丢失:await 用 while 循环重查条件;signal 前先改条件;用 signalAll 或精确 Condition。体现等待者 on 唤醒后重查条件。

Condition 精确唤醒避免惊群,用 while 循环与先改条件防信号丢失。

#
★★

31. 并发集合的弱一致性迭代器在快照语义上的取舍

并发集合的弱一致性迭代器在快照语义上的取舍是什么?

  • 弱一致性
  • 快照语义
  • 取舍

弱一致性迭代器(ConcurrentHashMap、CopyOnWriteArrayList 等):迭代时不抛 ConcurrentModificationException,但迭代器不保证反映迭代开始后的所有修改(可能看到部分、重复、漏掉)。快照语义取舍:1) 无锁、可并发遍历(性能好);2) 非严格快照(CopyOnWrite 是快照,CHM 是弱一致);3) 适合统计/批量处理,不适合需精确一致迭代。取舍:弱一致换并发性能,需严格快照用 CopyOnWrite 或锁。

弱一致迭代无锁并发,但非精确快照。需严格快照用 CopyOnWrite/锁。

#
★★

32. 责任链模式在并发任务预处理/后处理中的应用

责任链模式在并发任务预处理/后处理中的应用是什么?

  • 责任链
  • 预处理/后处理
  • 并发

责任链模式:把任务通过多个处理器链式处理(每个处理器决定是否继续)。并发任务预处理/后处理:1) 预处理链(校验、鉴权、上下文设置)在任务执行前依次处理;2) 后处理链(清理、日志、指标)在任务执行后处理。责任链用链式处理器组织"预处理/后处理",可扩展、解耦。并发场景:处理器无状态(线程安全),链按顺序执行,通常在执行线程内。用于任务包装、拦截器、事件处理。

责任链组织预处理/后处理,处理器无状态线程安全,链式执行。

#
★★

33. 异步任务的编排模式,回调、Future 与事件驱动三者的边界

异步任务的编排模式:回调、Future 与事件驱动三者的边界是什么?

  • 回调
  • Future
  • 事件驱动

三种异步编排:1) 回调(回调地狱):完成时调用回调,嵌套复杂;2) Future:阻塞/轮询获取,可超时/取消,但难组合;3) 事件驱动(反应式/事件循环):事件触发后续,无阻塞、可组合、背压。边界:回调适合简单单次异步;Future 适合单任务结果获取;事件驱动适合高并发流式、复杂编排。三者按复杂度与并发需求选择。现代:CompletableFuture(Future 增强)与反应式(事件驱动)为主。

回调简单、Future 单任务、事件驱动流式。按复杂度选,现代用 CompletableFuture/反应式。

#
★★

34. 多线程下单例服务的状态管理,无状态服务与不可变配置

多线程下单例服务的状态管理:无状态服务与不可变配置是什么?

  • 无状态服务
  • 不可变配置
  • 状态管理

多线程下单例服务(Spring Bean 单例)的状态管理:无状态服务(不持有可变字段,只处理入参)天然线程安全,多线程可安全并发调用。若需配置,用不可变配置(final 字段 + 不可变对象,构造时注入),安全发布。避免单例持有可变状态(计数器、缓存),否则需同步。实践:单例服务无状态化 + 不可变配置,最大化线程安全。可变状态用 ThreadLocal/外部存储。

单例服务无状态化 + 不可变配置,多线程安全。避免单例可变状态。

#
★★

35. 并发配置热更新,Copy-on-Write 配置对象与原子引用

并发配置热更新:Copy-on-Write 配置对象与原子引用是什么?

  • 配置热更新
  • Copy-on-Write
  • 原子引用

配置热更新:运行时更新配置,不影响运行。用 Copy-on-Write + 原子引用:配置封装为不可变对象,用 AtomicReference 持有;更新时构造新配置对象 CAS 替换引用,读者读到旧或新完整配置(原子快照)。无锁、读不阻塞。实现:AtomicReference 持有不可变配置快照,更新时构造新对象并 CAS 替换引用。热更新让配置变更即时生效,读者读到一致快照。

Copy-on-Write + 原子引用实现配置热更新,读安全、更新原子、无锁。

#
★★

36. 双重检查锁定在资源池初始化中的应用与陷阱

双重检查锁定在资源池初始化中的应用与陷阱是什么?

  • DCL
  • 资源池初始化
  • 陷阱

DCL 用于资源池(连接池/线程池)初始化:volatile 引用 + 双重检查,避免重复初始化。陷阱:1) 缺 volatile → 半初始化对象(最常错);2) 初始化失败 → 引用已赋值但池不可用,需处理失败;3) 懒初始化与并发首请求竞争。应用:延迟初始化资源池,volatile 保证安全发布。正确做法:volatile + 双重检查 + 初始化失败处理(重置引用)。

DCL 初始化资源池需 volatile 防半初始化,处理失败重置。陷阱是缺 volatile 与失败处理。

#
★★

37. 测试中的并发控制,如何用并发工具类验证线程安全

测试中的并发控制:如何用并发工具类验证线程安全?

  • 并发测试
  • 工具类
  • 验证

验证线程安全用并发工具类:1) CountDownLatch 同时启动多个线程执行操作;2) CyclicBarrier 让线程同步就绪;3) 用 AtomicInteger/计数器验证结果正确性;4) 用 jcstress 做并发压力测试(多种交错);5) 用 Semaphore 控制并发度。策略:多线程并发执行临界操作,断言结果符合预期(不变量)、无异常。jcstress 是标准并发验证工具。单测无法覆盖交错,需并发工具+压力测试。

并发测试用 CountDownLatch/Barrier 控制时序,jcstress 验证交错。断言不变量。

#
★★

38. 线程池任务的装饰器模式,包装 Runnable 实现超时、埋点与清理

线程池任务的装饰器模式:包装 Runnable 实现超时、埋点与清理是什么?

  • 装饰器
  • 包装 Runnable
  • 超时/埋点/清理

装饰器模式包装 Runnable:在提交前包装任务,实现横切逻辑:1) 超时:任务内记录开始时间,超时告警/放弃;2) 埋点:记录提交/开始/结束时间,统计耗时;3) 清理:finally 中清理 ThreadLocal、归还连接;4) 异常捕获与日志。包装器统一注入,不改业务代码。实现:自定义 Runnable 包装器,在 run() 中 try-finally 包裹。线程池提交时用包装器,统一横切增强。

装饰器包装 Runnable 统一超时/埋点/清理/异常,横切增强不改业务。

#
★★

39. 观察者模式与事件总线的线程模型,同步/异步/事务事件的取舍

观察者模式与事件总线的线程模型:同步/异步/事务事件的取舍是什么?

  • 观察者模式
  • 事件总线
  • 线程模型

观察者模式/事件总线:事件发布→监听器处理。线程模型:1) 同步事件(发布线程直接调用监听器,简单但发布阻塞);2) 异步事件(事件总线用线程池异步处理,发布不阻塞但顺序/上下文需注意);3) 事务事件(监听器在事务中/后执行,@TransactionalEventListener)。取舍:同步保序简单但阻塞发布;异步提高吞吐但需处理并发/上下文;事务事件绑定事务边界。按"是否需响应、是否阻塞、事务需求"选择。

同步/异步/事务事件按发布阻塞、并发、事务边界取舍。异步用线程池。

#
★★

40. 并发任务的异常聚合模式,CompletableFuture 与结构化并发的异常传播

并发任务的异常聚合模式:CompletableFuture 与结构化并发的异常传播是什么?

  • 异常聚合
  • CompletableFuture
  • 结构化并发

并发任务异常聚合:1) CompletableFuture:allOf 收集多任务,异常沿链传播(handle/exceptionally 处理),或 get 后逐个检查;2) 结构化并发(StructuredTaskScope):子任务异常聚合到作用域,策略(ShutdownOnFailure)短路,join 抛整体异常。差异:CF 异常分散在链中,需手动聚合;SScope 异常结构化聚合、级联取消。异常聚合模式:集中处理并发任务的失败,避免异常丢失。SScope 更结构化。

CF 异常沿链传播、SScope 结构化聚合。SScope 提供更明确的整体失败语义。

#
★★

41. 懒加载的并发安全,双重检查与静态内部类在单例初始化上的对比

懒加载的并发安全:双重检查与静态内部类在单例初始化上的对比是什么?

  • DCL
  • 静态内部类
  • 对比

懒加载并发安全:DCL(volatile + 双重检查)与静态内部类(holder class)都实现懒加载+线程安全。DCL 需 volatile 防半初始化,可手动控制;静态内部类靠类加载机制(首次访问时初始化),无锁、简单、天然安全。对比:静态内部类更简单可靠(推荐),DCL 需 volatile 与细心。两者都延迟初始化单例。选择偏好静态内部类。

静态内部类靠类加载线程安全、简单,DCL 需 volatile。静态内部类更推荐。

#
★★

42. 状态机模式与并发控制,状态转移的原子性保证

状态机模式与并发控制:状态转移的原子性保证是什么?

  • 状态机
  • 状态转移
  • 原子性

状态机并发控制:状态转移必须原子(确保合法转移、无并发冲突)。实现:1) 状态用 AtomicInteger/AtomicReference,CAS 转移(仅合法转移成功);2) 不合法的转移 CAS 失败;3) 状态+版本号防 ABA;4) 复杂转移用锁包裹。原子性保证:CAS 使"检查+转移"原子,避免并发下状态错乱。状态机用 CAS 保证"一次只有一个线程转移成功且转移合法"。

状态转移用 CAS 原子化,保证合法转移唯一、无并发冲突。

#
★★

43. 不可变值对象在线程间传递的安全发布方式

不可变值对象在线程间传递的安全发布方式是什么?

  • 不可变值对象
  • 安全发布
  • 传递

不可变值对象(所有字段 final、不可变)在线程间传递的安全发布方式:1) final 字段(构造冻结,安全发布);2) volatile/原子引用(发布可见);3) 静态初始化(类加载);4) 锁保护(happens-before)。由于不可变,发布后无需同步修改。安全发布方式保证"读者看到完整对象"(final 字段冻结)。传递时用 volatile 引用或直接传引用(final 保证字段值)。不可变对象安全发布简单。

不可变值对象靠 final 冻结 + 安全发布方式(volatile/锁/静态),读者看到完整状态。

#
★★

44. 请求级上下文(Request Scope)与线程安全,为什么共享可变请求对象危险

请求级上下文(Request Scope)与线程安全:为什么共享可变请求对象危险?

  • Request Scope
  • 共享可变对象
  • 危险

请求级上下文(Request Scope)每个请求独立,但若被多线程共享的可变请求对象(如请求体、状态)被并发修改,会竞态:多线程读写同一可变对象,数据错乱、不一致。危险:1) 请求对象被异步任务/线程池共享,多线程修改;2) 可变状态(如请求计数器)被并发改。应对:请求级对象应线程封闭(每请求/每线程)或用不可变/ThreadLocal,避免跨线程共享可变请求对象。共享可变对象是危险源。

共享可变请求对象被多线程并发改造成竞态。请求级应线程封闭或不可变。

#
★★

45. 锁获取顺序与死锁预防,全序锁 vs 部分序锁

锁获取顺序与死锁预防:全序锁 vs 部分序锁是什么?

  • 锁获取顺序
  • 全序锁
  • 部分序锁

死锁预防:所有线程按一致的全序获取锁(如按锁的 ID 排序),避免循环等待。全序锁:所有锁有全局顺序,线程按该顺序获取,杜绝死锁。部分序锁:只对部分锁对定义顺序,其余无约束,可能死锁。全序锁简单但过度(所有锁都排序);部分序锁灵活但需保证涉及的所有锁对有序。实践:多锁时按固定顺序获取(如先锁 id 小的),用 tryLock 超时兜底。全序锁是防死锁的可靠方法。

全序锁按统一顺序获取杜绝循环等待,部分序锁需保证有序子集。防死锁用全序+超时。

#
★★

46. 线程池任务路由,按任务类型选择专用线程池的隔离模式

线程池任务路由:按任务类型选择专用线程池的隔离模式是什么?

  • 任务路由
  • 专用线程池
  • 隔离

任务路由:按任务类型(业务/优先级/IO 类型)路由到专用线程池,实现隔离。模式:1) 为不同任务类型建独立线程池(如 IO 池、计算池、慢任务池);2) 提交时按类型路由到对应池;3) 各池独立参数、独立监控、互不影响。隔离收益:一种任务占满只影响自己的池,不拖累其他。代价:资源利用低(多池预留线程)。按任务特性(阻塞/计算/优先级)路由到专用池,隔离故障。

任务路由到专用池实现隔离,按类型分池。隔离故障但资源利用低。

#
★★

47. 线程安全的消息转换器设计,无状态处理器与线程局部缓冲

线程安全的消息转换器设计:无状态处理器与线程局部缓冲是什么?

  • 消息转换器
  • 无状态处理器
  • 线程局部缓冲

线程安全的消息转换器:设计为无状态处理器(不持有可变状态,只处理入参),天然线程安全,可被多线程共享调用。若需缓冲(复用临时对象),用线程局部缓冲(ThreadLocal 存每线程的临时对象),避免共享可变缓冲。关键:无状态(线程安全)+ 线程局部缓冲(复用但不共享)。避免把可变状态放转换器实例。转换器无状态化 + 缓冲线程本地化。

无状态处理器线程安全,缓冲用 ThreadLocal 避免共享。消息转换器应无状态。

#
★★

48. 会话级状态的线程安全,Session 与线程池共享的冲突

会话级状态的线程安全:Session 与线程池共享的冲突是什么?

  • 会话级状态
  • Session
  • 线程池共享

会话级状态(用户会话、Session)若被线程池任务共享,多线程并发访问同一会话可变状态,冲突:1) 会话数据被多任务并发改,竞态;2) 会话与线程池解耦(线程池任务不绑定会话线程)。应对:1) 会话状态线程封闭(每请求/会话独立,不跨线程共享);2) 共享会话用同步/不可变;3) 避免在线程池任务中直接改会话可变状态。会话级状态应线程隔离,线程池共享可变会话易冲突。

会话状态被线程池并发共享易冲突。会话应线程封闭或共享时同步。

#
★★

49. 模板方法模式在并发任务骨架中的应用,同步、加锁与超时的固定顺序

模板方法模式在并发任务骨架中的应用:同步、加锁与超时的固定顺序是什么?

  • 模板方法
  • 并发任务骨架
  • 固定顺序

模板方法模式定义并发任务骨架:固定顺序执行"加锁→执行→超时处理→释放",子类实现具体步骤。骨架(模板方法):1) 获取锁(固定顺序);2) 执行业务(抽象方法);3) 超时检查;4) finally 释放锁。固定顺序保证一致性(如先加锁再执行、超时后释放)。并发任务骨架用模板方法统一"同步/加锁/超时"的固定顺序,子类只实现业务,避免重复与错误(如忘释放锁)。

模板方法封装并发骨架的固定顺序(加锁→执行→释放),子类实现业务,保证一致性。

#
★★

50. 策略模式在并发限流/重试策略选择中的应用

策略模式在并发限流/重试策略选择中的应用是什么?

  • 策略模式
  • 限流/重试
  • 选择

策略模式定义可替换的限流/重试策略接口,运行时选择具体策略:1) 限流策略(信号量/令牌桶/计数),可替换;2) 重试策略(固定/指数/随机退避),可配置。并发中策略模式:把限流/重试算法抽象为策略,按场景注入(如不同依赖不同重试策略)。好处:可扩展、可配置、算法与业务解耦。实现:Strategy 接口 + 具体实现 + 选择器。并发限流/重试用策略模式灵活切换。

策略模式把限流/重试算法抽象可替换,按场景选择。解耦、可扩展。

#
★★

51. 线程安全的类型转换器,不可变转换器与缓存

线程安全的类型转换器:不可变转换器与缓存是什么?

  • 类型转换器
  • 不可变
  • 缓存

线程安全的类型转换器:设计为不可变(无可变状态,只含转换逻辑),天然线程安全,可多线程共享。若需缓存转换结果,用线程安全缓存(ConcurrentHashMap)或不可变缓存快照。关键:转换器本身不可变(无状态),缓存用并发安全结构。避免转换器持有可变状态(如共享临时缓冲)。不可变转换器 + 并发缓存实现线程安全。

不可变转换器(无状态)线程安全,缓存用并发结构。避免可变状态。

#
★★

52. 拦截器模式在并发任务生命周期钩子(before/after)中的应用

拦截器模式在并发任务生命周期钩子(before/after)中的应用是什么?

  • 拦截器
  • 生命周期钩子
  • before/after

拦截器模式在并发任务生命周期钩子:beforeExecute/afterExecute 或自定义拦截器,在任务执行前后注入逻辑(上下文设置、耗时统计、清理、鉴权)。应用:1) 任务前设置 MDC/TraceId、校验;2) 任务后清理、统计、日志;3) 异常处理。与 ThreadPoolExecutor 的 beforeExecute/afterExecute 扩展点对应。拦截器统一横切"任务生命周期",不改业务。用拦截器实现任务级 before/after 钩子。

拦截器在任务 before/after 钩子注入横切逻辑(上下文、统计、清理),统一增强。

#
★★

53. 参数解析与线程安全,局部变量优先于共享可变状态

参数解析与线程安全:局部变量优先于共享可变状态是什么?

  • 参数解析
  • 局部变量
  • 共享可变状态

线程安全实践:参数解析用局部变量(方法内),避免共享可变状态。局部变量线程封闭(栈封闭),天然安全;共享可变状态(对象字段、静态变量)被多线程并发访问需同步。原则:优先用局部变量传参,避免把状态放共享可变位置;必须共享也尽量不可变或同步。参数解析(如请求参数)应在方法内处理为局部变量,不写共享字段。局部变量优先于共享可变状态。

局部变量线程封闭安全,共享可变状态需同步。参数解析用局部变量优先。

#
★★

54. 代理模式在并发控制中的应用,同步代理与远程代理

代理模式在并发控制中的应用:同步代理与远程代理是什么?

  • 代理模式
  • 同步代理
  • 远程代理

代理模式在并发控制:1) 同步代理(Synchronized Proxy):包装对象,方法加锁(synchronized/ReentrantLock),实现线程安全的访问控制(如 Collections.synchronizedList);2) 远程代理:代理负责远程调用,隐藏网络细节(并发下注意连接池/超时)。同步代理用于"给已有对象加线程安全"(不改原对象);远程代理用于分布式调用。并发控制用同步代理包裹临界对象,提供统一同步入口。

同步代理包装对象加锁实现线程安全,远程代理封装远程调用。代理模式控制并发/远程访问。

#
★★

55. 事务与线程绑定,ThreadLocal 事务上下文在多线程下的边界

事务与线程绑定:ThreadLocal 事务上下文在多线程下的边界是什么?

  • 事务绑定
  • ThreadLocal 上下文
  • 多线程边界

事务与线程绑定:Spring 事务用 ThreadLocal 存事务上下文(连接、传播状态),绑定到当前线程。边界:1) 事务在单线程内生效(跨线程不自动传播);2) 线程池任务中 ThreadLocal 事务上下文不继承(需显式传播或新开事务);3) 事务边界 = 线程边界(同一线程内事务串行)。多线程下:每个线程独立事务,跨线程共享事务需特殊处理(如传播/同步)。边界:ThreadLocal 事务不跨线程,异步任务需新事务或显式传播。

ThreadLocal 事务绑定线程,不跨线程传播。异步/线程池需新事务或显式传播。

#
★★

56. 并发工具的横切织入,如何统一为任务添加重试与超时

并发工具的横切织入:如何统一为任务添加重试与超时?

  • 横切织入
  • 重试
  • 超时

并发工具横切织入:统一为任务添加重试与超时,不改业务代码。方式:1) 装饰器包装任务(重试逻辑、超时检查);2) 代理/拦截器统一注入;3) 用 CompletableFuture 的 orTimeout 统一超时;4) 用 RetryTemplate/AOP 统一重试。横切织入把"重试/超时"从业务中剥离,统一配置。实现:提交时包装任务(重试次数、超时),或 AOP 注解。核心是"横切关注点统一织入"。

装饰器/代理/AOP 统一织入重试与超时,业务解耦。横切关注点统一配置。

#
★★

57. 资源提供者模式,对象工厂的线程安全初始化

资源提供者模式:对象工厂的线程安全初始化是什么?

  • 资源提供者
  • 对象工厂
  • 线程安全初始化

资源提供者/对象工厂:创建并管理资源(连接、线程池)。线程安全初始化:1) 工厂单例(volatile/静态内部类);2) 初始化用 DCL/懒加载+volatile;3) 资源池并发获取(Semaphore/队列);4) 初始化失败处理。核心:工厂初始化线程安全(只初始化一次)+ 资源获取并发安全(池化)。用 holder class/DCL 初始化工厂,用并发池管理资源。

工厂线程安全初始化(单例)+ 资源池并发获取。holder class/DCL + 池化。

#
★★

58. 共享资源的并发访问,资源池化与读写隔离

共享资源的并发访问:资源池化与读写隔离是什么?

  • 资源池化
  • 读写隔离
  • 并发访问

共享资源并发访问:1) 资源池化:把有限资源(连接)池化,并发获取/归还,控制上限(信号量);2) 读写隔离:读多写少用读写锁/不可变快照,写与读隔离(Copy-on-Write);3) 隔离:资源按类型隔离(不同池)。实践:资源池化控制并发 + 读写隔离(读无锁、写复制)提升吞吐。共享资源用池化+读写隔离,避免竞争与资源耗尽。

资源池化控制并发上限,读写隔离(读无锁写复制)提升并发。共享资源并发访问的两种策略。

#
★★

59. 同步与异步客户端在并发模型上的差异,每请求一线程 vs 事件循环

同步与异步客户端在并发模型上的差异:每请求一线程 vs 事件循环是什么?

  • 同步客户端
  • 异步客户端
  • 并发模型

同步客户端:每请求一线程(阻塞 IO),线程阻塞等待响应,受线程数限制,简单但并发有限。异步客户端:事件循环(非阻塞 IO),少量线程处理大量请求,通过回调/事件驱动,高并发、吞吐高但复杂。差异:同步"线程换并发"(线程数受限),异步"事件循环换并发"(少量线程高并发)。虚拟线程出现后,同步客户端(虚拟线程)也能高并发。选择:简单场景同步,高并发 IO 用异步或虚拟线程。

同步每请求一线程(线程受限),异步事件循环(少量线程高并发)。虚拟线程让同步可高并发。

#
★★

60. 模式匹配与并发缓存,路由表的并发读写一致性

模式匹配与并发缓存:路由表的并发读写一致性是什么?

  • 模式匹配
  • 并发缓存
  • 路由表一致性

路由表(配置/路由规则)并发读写:用并发缓存(ConcurrentHashMap)或不可变快照保证一致性。模式匹配:路由表按规则匹配请求。并发一致性:1) 路由表不可变快照(Copy-on-Write + 原子引用),读一致、更新原子;2) 并发缓存(ConcurrentHashMap)保证并发读写安全;3) 更新与其他读隔离。实践:路由表用不可变快照/并发缓存,读无锁、写原子替换,保证匹配一致性。避免读时看到半更新路由。

路由表用不可变快照/并发缓存,读一致、写原子替换。避免半更新。

#
★★

61. 错误对象在并发异常处理中的线程安全,异常栈与错误码的不可变性

错误对象在并发异常处理中的线程安全:异常栈与错误码的不可变性是什么?

  • 错误对象
  • 异常栈
  • 不可变性

错误对象(异常、错误码)在并发中应不可变:异常对象创建后不修改(栈、错误码),可安全共享。异常栈在构造时生成(线程安全),错误码是常量。若异常对象含可变状态(如计数器),并发共享会竞态。实践:1) 异常对象不可变(只读字段);2) 错误码用枚举/常量(不可变);3) 避免共享可变错误对象。异常栈与错误码的不可变性保证并发异常处理安全。

异常/错误码不可变(只读),线程安全。共享可变错误对象会竞态。

#
★★

62. 依赖升级对并发语义的影响,JDK 与框架版本变更中的线程模型变化

依赖升级对并发语义的影响:JDK 与框架版本变更中的线程模型变化是什么?

  • 依赖升级
  • 线程模型
  • 版本变更

依赖升级(JDK/框架版本)可能改变并发语义:1) JDK 版本变更(如偏向锁禁用、虚拟线程、内存模型演进)改变线程模型;2) 框架版本(如线程池默认值、异步行为)变化;3) 并发 API 语义变化(如 weakCompareAndSet)。影响:升级后并发行为可能变化(性能、线程数、语义)。应对:升级前验证并发行为、阅读 release notes、压测;关注线程模型差异(如容器线程数、虚拟线程)。依赖升级需评估并发语义变化。

版本升级改变线程模型/并发语义,升级前需验证与压测,关注 release notes。

#
★★

63. 国际化资源的多线程安全,不可变资源包与缓存

国际化资源的多线程安全:不可变资源包与缓存是什么?

  • 国际化资源
  • 不可变资源包
  • 缓存

国际化资源(i18n 资源包)多线程安全:资源包设计为不可变(加载后只读),天然线程安全可共享。缓存(ResourceBundle 缓存)用线程安全结构(ConcurrentHashMap)或懒加载+volatile。关键:1) 资源包不可变(内容只读);2) 缓存并发安全(CHM 或 double-checked);3) 懒加载初始化安全。资源包不可变 + 并发缓存实现多线程安全加载与访问。

资源包不可变(只读)+ 并发缓存(CHM/DCL),多线程安全加载访问。

#
★★

64. Spring 容器的事件机制(ApplicationEvent/ApplicationListener)

Spring 容器的事件机制(ApplicationEvent/ApplicationListener)是什么?

  • ApplicationEvent
  • ApplicationListener
  • 事件机制

Spring 事件机制:ApplicationEvent 表示事件,ApplicationListener 监听,ApplicationEventPublisher 发布。默认同步(发布线程调用监听器,阻塞发布);可配置异步(@Async/@EventListener 异步用线程池)。多线程安全:事件对象若共享可变状态需注意;异步监听跨线程。Spring 事件用于解耦(发布-监听),支持事务事件(@TransactionalEventListener)。线程模型:同步/异步按配置。事件机制是观察者模式的 Spring 实现。

Spring 事件默认同步、可异步,用于解耦。异步监听用线程池,事件对象需注意共享。

#
★★

65. 配置属性的并发读取,原子快照与最终一致性的边界

配置属性的并发读取:原子快照与最终一致性的边界是什么?

  • 配置读取
  • 原子快照
  • 最终一致

配置属性并发读取:1) 原子快照(不可变配置 + 原子引用):读者读到一致快照(旧或新),无中间态;2) 最终一致(多个配置字段分别更新):读者可能读到"部分新部分旧"的混合,最终收敛。边界:需"读时一致"(原子快照)用不可变配置+原子引用;可接受"最终一致"(短暂混合)用普通更新。原子快照保证一致性,最终一致更高性能但短暂不一致。按业务一致性需求选。

原子快照保证读一致,最终一致允许短暂混合。按一致性需求选择。

#
★★

66. 推送模型的线程安全,长连接与写线程的并发控制

推送模型的线程安全:长连接与写线程的并发控制是什么?

  • 推送模型
  • 长连接
  • 并发控制

推送模型(长连接/WebSocket)线程安全:多个写线程并发写同一条连接,需并发控制:1) 写锁/队列串行化写(避免并发写交错);2) 连接状态管理(连接池/注册表)用并发集合;3) 写超时与断连处理。长连接共享(多线程写)需同步写,避免数据交错与连接状态竞态。实践:写操作加锁或入队,连接注册表用 ConcurrentHashMap,断连处理原子。推送写并发控制是线程安全关键。

长连接多线程写需串行化(锁/队列),连接注册表并发集合。写并发控制。

#
★★

67. Thread-Per-Message 模式在虚拟线程时代的简化与 Executor 框架的边界

Thread-Per-Message 模式在虚拟线程时代的简化与 Executor 框架的边界是什么?

  • Thread-Per-Message
  • 虚拟线程
  • Executor 边界

Thread-Per-Message:每个消息/请求一个线程。虚拟线程时代:虚拟线程廉价,Thread-Per-Message 简化(每任务一个虚拟线程,无需池化),阻塞卸载,高并发。Executor 框架边界:虚拟线程虽免池化,但需要限流/隔离/管理时仍用 Executor(虚拟线程 Executor/信号量)。边界:纯 IO 并发用虚拟线程 Thread-Per-Message(免池化);需限流、隔离、生命周期管理用 Executor。虚拟线程简化 Thread-Per-Message,Executor 保留控制能力。

虚拟线程让 Thread-Per-Message 免池化,Executor 保留限流/隔离控制。按需选择。

#
★★

68. 事务传播与线程边界,REQUIRES_NEW 在并发调用下的连接分配

事务传播与线程边界:REQUIRES_NEW 在并发调用下的连接分配是什么?

  • 事务传播
  • REQUIRES_NEW
  • 连接分配

REQUIRES_NEW:新开事务(挂起当前事务),在并发调用下:1) 每个线程各自新事务、独立连接;2) 连接分配受连接池限制(并发新事务需多个连接);3) 线程边界:REQUIRES_NEW 不跨线程,各线程独立事务。并发调用下,多线程各自 REQUIRES_NEW 会占用多个连接,需连接池容量匹配。事务传播(REQUIRES_NEW)在并发下独立连接,注意连接池容量与线程数匹配。

REQUIRES_NEW 每线程独立新事务、独立连接,并发下需连接池容量匹配。

#
★★

69. Two-Phase Termination 模式的 interrupt 协作与 join 等待在优雅停机中的实现

Two-Phase Termination 模式的 interrupt 协作与 join 等待在优雅停机中的实现是什么?

  • Two-Phase Termination
  • interrupt
  • join 等待

Two-Phase Termination(两阶段终止):优雅停机时,先通知线程终止(interrupt),再等待线程完成(join)。实现:1) 阶段一:调用 interrupt() 发出终止信号(协作式);2) 线程检查中断标志/响应 InterruptedException,清理后退出;3) 阶段二:join() 等待线程终止(带超时),超时兜底。两阶段保证"先优雅通知、再等待完成",避免强制杀线程。优雅停机用 interrupt + join,配合超时与清理。

Two-Phase Termination = interrupt 通知 + join 等待,配合超时与清理。优雅停机标准模式。

#
★★

70. 配置文件的并发加载与热更新,不可变配置快照模式

配置文件的并发加载与热更新:不可变配置快照模式是什么?

  • 配置加载
  • 热更新
  • 不可变快照

配置文件并发加载与热更新用不可变配置快照模式:配置文件解析为不可变配置对象,用 AtomicReference 持有;热更新时重新加载解析,CAS 替换快照引用,读者读到旧或新完整快照(原子)。并发加载:多线程读同一快照安全(不可变),加载用懒加载+volatile。模式:不可变快照 + 原子引用实现"读安全、更新原子、热更新"。配置热更新不阻塞读、一致快照。

不可变配置快照 + 原子引用,热更新原子替换,读安全一致。配置并发加载热更新标准模式。

#
★★

71. SPI 加载的并发安全,ServiceLoader 与缓存

SPI 加载的并发安全:ServiceLoader 与缓存是什么?

  • SPI 加载
  • ServiceLoader
  • 缓存

SPI 加载(ServiceLoader)并发安全:ServiceLoader 加载服务可能被多线程并发调用。策略:1) 懒加载+volatile 缓存(double-checked)避免重复加载;2) ServiceLoader 迭代器并发使用需注意(非线程安全,需同步或缓存);3) 缓存已加载服务(并发安全)。实践:服务实例用懒加载单例(volatile/DCL),服务缓存用并发结构。SPI 加载并发安全靠"懒加载缓存 + 并发安全"。

SPI 加载用懒加载缓存(volatile/DCL)保证并发安全,避免重复加载。ServiceLoader 迭代需同步。

#
★★

72. 热点路径的并发优化,减少锁竞争与伪共享

热点路径的并发优化:减少锁竞争与伪共享是什么?

  • 热点路径
  • 锁竞争
  • 伪共享

热点路径并发优化:1) 减少锁竞争:锁粒度细分、无锁(CAS)、锁分段、读写锁(读多写少);2) 减少伪共享:缓存行填充(@Contended)、热字段分散;3) 减少同步:不可变、线程封闭、无锁算法。热点路径(高频执行)的锁竞争与伪共享是性能瓶颈。优化手段:细粒度锁、CAS、缓存行填充、无锁。核心是"热点路径减少竞争与伪共享"。

热点路径优化 = 减少锁竞争(细粒度/无锁)+ 减少伪共享(缓存行填充)。

#
★★

73. 健康检查的并发执行,超时与并行探测

健康检查的并发执行:超时与并行探测是什么?

  • 健康检查
  • 超时
  • 并行探测

健康检查并发执行:并行探测多个依赖(并行执行,不串行阻塞),每个探测设超时(避免单个探测拖慢)。实现:1) 并行用线程池/CompletableFuture 并发探测;2) 每个探测设超时(get(timeout)/orTimeout);3) 聚合结果(全部健康/部分异常),超时视为不健康。并发执行 + 超时兜底,避免健康检查串行慢或挂起。健康检查应并行、超时、聚合。

健康检查并行探测 + 每项超时 + 聚合结果。避免串行慢或挂起。

#
★★

74. 并发代码中的不可变数据优化,final 与有效不可变

并发代码中的不可变数据优化:final 与有效不可变是什么?

  • final
  • 有效不可变
  • 不可变优化

并发代码不可变优化:1) final 字段:构造后冻结,安全发布,线程安全;2) 有效不可变(effectively immutable):对象虽非 final 但构造后不再修改(发布后不写),可安全共享。优化:把数据设计为不可变(final/有效不可变),避免锁与同步,提升并发性能。关键:构造后不修改、安全发布。有效不可变需保证"发布后无人修改"。不可变数据是并发性能的优化。

final 冻结 + 有效不可变(发布后不写)实现线程安全,避免同步。并发数据不可变优化。

#
★★

75. 配置优先级与并发覆盖,多数据源配置的原子切换

配置优先级与并发覆盖:多数据源配置的原子切换是什么?

  • 配置优先级
  • 多数据源
  • 原子切换

多数据源配置(默认/env/远程)有优先级,并发覆盖时需原子切换:1) 配置合并为不可变快照,原子替换(AtomicReference);2) 更新时按优先级合并,CAS 替换,避免并发覆盖部分用力;3) 读者读到一致快照。并发覆盖:多个数据源同时更新,需原子合并替换,避免读到混合配置。实践:配置快照不可变 + 原子引用,合并按优先级,原子切换。多数据源配置原子切换保证一致性。

多数据源配置按优先级合并为不可变快照,原子引用切换,避免并发覆盖混合。

#
★★

76. 多数据源与线程绑定,路由数据源在并发下的上下文管理

多数据源与线程绑定:路由数据源在并发下的上下文管理是什么?

  • 多数据源
  • 路由数据源
  • 上下文

路由数据源(DynamicDataSource)按上下文(如租户、读写)选择数据源。并发下上下文管理:1) 路由上下文用 ThreadLocal(线程绑定),线程池任务需传递(TransmittableThreadLocal);2) 上下文设置/清理(防泄漏);3) 异步/线程池路由需显式传递上下文。并发下:路由数据源读 ThreadLocal 选数据源,线程池复用需清理与传递。上下文管理保证路由正确、防串扰。

路由数据源用 ThreadLocal 上下文,线程池需传递/清理。上下文管理防串扰。

#
★★

77. 流式写出的线程安全,异步写出与连接关闭的竞争

流式写出的线程安全:异步写出与连接关闭的竞争是什么?

  • 流式写出
  • 异步写出
  • 连接关闭竞争

流式写出线程安全:异步写出与连接关闭可能竞争(写线程与关闭线程并发)。竞争:1) 写线程写连接时,关闭线程关闭连接,写失败/异常;2) 写-读-关并发。处理:1) 写与关用锁/原子状态串行化;2) 关闭前检查状态、写前检查连接;3) 捕获写异常(连接关闭)合理处理。流式写出并发安全:写操作加锁/状态检查,关闭原子,捕获关闭异常。避免写与关竞争。

异步写与关连接竞争,用锁/状态检查串行化,捕获写异常。

#
★★

78. 嵌入式容器的线程模型,容器线程池与业务并发的关系

嵌入式容器的线程模型:容器线程池与业务并发的关系是什么?

  • 嵌入式容器
  • 线程池
  • 业务并发

嵌入式容器(Tomcat/Jetty)线程模型:容器线程池处理连接/请求,业务线程池处理业务。关系:1) 容器线程只做 IO(接收/转发),业务在业务池执行;2) 容器线程数决定并发请求数,业务池决定业务并发;3) 若业务直接在容器线程执行(无业务池),容器线程被业务占满,影响新请求。实践:容器线程与业务池分离,业务池隔离,避免业务阻塞容器。容器线程池与业务并发需隔离规划。

容器线程池 IO 转发,业务池处理业务,隔离避免业务阻塞容器。虚拟线程可替代容器线程。

#
★★

79. JFR 采样与并发诊断,锁竞争事件的采集与分析

JFR 采样与并发诊断:锁竞争事件的采集与分析是什么?

  • JFR 采样
  • 锁竞争事件
  • 诊断

JFR 采集锁竞争事件:jdk.JavaMonitorEnter(锁等待)、jdk.JavaMonitorBlocked(锁阻塞)、jdk.ThreadPark(park)、jdk.JavaThreadSamples 等,记录锁等待时长、线程、锁对象。分析:1) 按锁等待时长排序定位热点锁;2) 看等待线程与持锁线程,分析竞争;3) 结合线程栈定位锁点。JFR 低开销,适合生产采样。锁竞争诊断用 JFR 事件量化等待时长与热点锁。

JFR 锁事件(JavaMonitorEnter 等)量化锁等待,定位热点锁。低开销生产采样。

#
★★

80. 锁优化失效的运行时表现,偏向锁撤销与锁竞争

锁优化失效的运行时表现:偏向锁撤销与锁竞争是什么?

  • 锁优化失效
  • 偏向锁撤销
  • 锁竞争

锁优化失效的运行时表现:1) 偏向锁撤销(多线程竞争同一锁时,撤销偏向频繁,STW 暂停、开销大);2) 锁竞争(轻量锁自旋失败升级重量级,线程阻塞、上下文切换);3) 锁消除/粗化失效(对象逃逸/相邻锁无法合并)。表现:CPU 高(自旋/撤销)、线程 BLOCKED(重量级)、延迟抖动。诊断:JFR 锁事件、线程 dump、GC 暂停。锁优化失效说明竞争升高,需优化锁粒度或改无锁。

锁优化失效表现:偏向撤销、锁竞争升级、阻塞。JFR/dump 诊断,需优化。

#

81. 循环并行化,数据竞争与同步开销的权衡

循环并行化:数据竞争与同步开销的权衡是什么?

  • 循环并行化
  • 数据竞争
  • 同步开销

循环并行化:把循环迭代分到多线程并行。关键权衡:1) 数据竞争:迭代间共享数据需同步(否则竞态);2) 同步开销:加锁/原子开销可能抵消并行收益。权衡:1) 迭代独立(无共享)才安全并行;2) 共享数据用原子/局部归约减少同步;3) 任务粒度适中(并行收益 > 同步开销)。实践:独立迭代并行 + 归约(reduce)减少共享、控制粒度。循环并行化在"数据独立 + 粒度适中"时收益最大。

循环并行化权衡数据竞争与同步开销。独立迭代+归约+适中粒度。

#

82. 参数校验的线程安全,校验器无状态与共享校验上下文

参数校验的线程安全:校验器无状态与共享校验上下文是什么?

  • 参数校验
  • 校验器无状态
  • 共享上下文

参数校验线程安全:校验器设计为无状态(不持有可变状态,只处理入参),天然线程安全可共享。共享校验上下文(校验规则、配置)应不可变或线程安全。若校验器持有可变状态(如缓存计数器),多线程会竞态。实践:校验器无状态(规则入参传递)+ 共享上下文不可变/并发安全。参数校验器无状态化保证线程安全。

校验器无状态(只读入参)线程安全,共享上下文不可变。避免可变状态。

#

83. 依赖注入与线程安全,构造器注入保证不可变依赖

依赖注入与线程安全:构造器注入保证不可变依赖是什么?

  • 依赖注入
  • 构造器注入
  • 不可变依赖

依赖注入线程安全:构造器注入(constructor injection)在构造时注入依赖,字段 final/不可变,保证依赖不可变、安全发布。相比字段注入(setter,可变)更安全。构造器注入:依赖在构造时确定,final 字段(若可能),线程安全共享。实践:优先构造器注入,依赖接口不可变,单例服务共享。构造器注入保证依赖不可变与线程安全。

构造器注入在构造时确定依赖,配合 final 保证不可变、线程安全。比 setter 注入安全。

#

84. 生产者-消费者模式四种实现(BlockingQueue/wait-notify/Condition/Disruptor)的性能对比与选型

生产者-消费者模式四种实现(BlockingQueue/wait-notify/Condition/Disruptor)的性能对比与选型是什么?

  • BlockingQueue
  • wait-notify
  • Condition

生产者-消费者四种实现:1) BlockingQueue:有界/无界阻塞队列,简单,吞吐中等;2) wait-notify:手动实现,容易出错(惊群、丢唤醒),性能一般;3) Condition:精确唤醒,比 wait-notify 高效,性能好;4) Disruptor:无锁环形缓冲,预分配+缓存行填充,吞吐最高。选型:简单场景 BlockingQueue;需精确控制 Condition;超低延迟高吞吐用 Disruptor;wait-notify 不推荐。按性能需求与复杂度选。

性能排序:Disruptor > Condition > BlockingQueue > wait-notify。按吞吐与复杂度选。

#

85. 虚拟线程的开启方式(spring.threads.virtual.enabled)及其与 Tomcat/Jetty 线程模型的边界

虚拟线程的开启方式(spring.threads.virtual.enabled)及其与 Tomcat/Jetty 线程模型的边界是什么?

  • 虚拟线程开启
  • spring.threads.virtual.enabled
  • 容器线程模型

Spring Boot 开启虚拟线程:spring.threads.virtual.enabled=true,让容器(Tomcat/Jetty)用虚拟线程处理请求(每请求一虚拟线程)。边界:1) 虚拟线程替代容器线程池(Tomcat 用虚拟线程接收请求);2) 阻塞 IO 卸载载体线程,高并发;3) CPU 密集无收益;4) 需 JDK 21+。与容器线程模型:虚拟线程使容器线程池"无界"(每请求线程),受载体线程限制。实践:IO 密集服务开启虚拟线程,容器线程模型简化。

spring.threads.virtual.enabled 开启虚拟线程容器,每请求一虚拟线程,IO 密集高并发。CPU 密集无收益。

#

86. 环绕执行的并发模板,加锁、执行与释放的固定模式

环绕执行的并发模板:加锁、执行与释放的固定模式是什么?

  • 环绕执行
  • 加锁/执行/释放
  • 固定模式

环绕执行模板(execute-around):固定模式"加锁→执行→释放",用 try/finally 保证释放。模板方法/共享模板封装:1) 获取锁;2) try 执行(接受回调/抽象方法);3) finally 释放锁。保证锁一定释放(异常也释放)。实现:模板方法定义骨架,或提供 Template 类(接受 Lambda)。用环绕执行模板避免"忘释放锁"的错误。固定顺序(加锁/执行/释放)由模板保证。

环绕执行模板用 try/finally 保证加锁/执行/释放,避免忘释放。固定模式。

#

87. 配置校验的并发执行,启动校验与运行期校验的边界

配置校验的并发执行:启动校验与运行期校验的边界是什么?

  • 配置校验
  • 启动校验
  • 运行期校验

配置校验分启动与运行期:1) 启动校验:应用启动时校验配置(同步、单线程、失败即停),保证配置正确后才启动;2) 运行期校验:运行时校验(热更新配置、并发校验),需线程安全、可回滚。边界:启动校验单次、阻塞、失败停;运行期校验并发、动态、热更新。运行期校验需并发安全(不可变快照、原子切换),失败回滚旧配置。启动校验强校验,运行期校验温和。

启动校验单次阻塞,运行期校验并发动态。运行期校验需并发安全与回滚。

#

88. 静态资源的并发访问,不变文件与缓存一致性

静态资源的并发访问:不变文件与缓存一致性是什么?

  • 静态资源
  • 不变文件
  • 缓存一致性

静态资源并发访问:静态文件(不变)可安全并发读(不可变),无锁。缓存一致性:静态资源缓存(本地/CDN)需保证一致性:1) 文件不变则缓存永不失效;2) 文件更新需缓存失效(版本号/ETag);3) 并发缓存读用并发安全。静态资源不可变(只读)天然并发安全,缓存用版本/ETag 控制一致性。不变文件并发读安全,更新时缓存失效。

静态资源不可变并发读安全,缓存用版本/ETag 控制一致。不变文件天然安全。

#

89. 多语言互操作与并发,跨语言调用的线程模型

多语言互操作与并发:跨语言调用的线程模型是什么?

  • 多语言互操作
  • 跨语言调用
  • 线程模型

多语言互操作(JNI/外部等)线程模型:跨语言调用(Java→native/其他语言)的线程模型需注意:1) JNI 调用可能钉住/阻塞(虚拟线程下);2) native 调用线程亲和性/状态;3) 跨语言共享数据同步。并发:跨语言调用需明确线程模型(native 线程 vs Java 线程),避免阻塞载体线程;共享状态同步。多语言互操作线程模型需协调,否则阻塞/竞态。虚拟线程下 native 调用可能钉住。

跨语言调用线程模型需协调(JNI 钉住、native 阻塞),共享状态同步。虚拟线程下注意 pinning。

#

90. 安全随机数的并发使用,SecureRandom 的线程安全

安全随机数的并发使用:SecureRandom 的线程安全是什么?

  • SecureRandom
  • 线程安全
  • 并发使用

SecureRandom 是线程安全的(JDK 8+ 使用原子/自旋),可多线程共享。但并发使用可能竞争(同一实例多线程调用),热点时性能下降。实践:1) 共享 SecureRandom 实例(线程安全);2) 高并发时用线程本地实例(ThreadLocal)或预生成随机数;3) 避免每次 new(昂贵)。SecureRandom 线程安全但高并发竞争,可用 ThreadLocal 分散。并发使用注意安全与性能。

SecureRandom 线程安全,高并发竞争用 ThreadLocal 分散。避免每次 new。

#

91. 模式匹配与并发,模式变量在锁内外的生命周期

模式匹配与并发:模式变量在锁内外的生命周期是什么?

  • 模式匹配
  • 模式变量
  • 生命周期

模式匹配(Java 16+):模式变量在匹配分支内有效(作用域)。并发下:模式变量在锁内外生命周期:1) 模式变量只在匹配的作用域内(锁内匹配则锁内有效);2) 锁内的模式变量在锁外不可用(作用域结束);3) 并发访问共享对象时,模式变量的引用需注意对象状态。生命周期:模式变量跟随匹配作用域,锁内匹配的变量锁外不可用。并发下模式变量作用域与锁边界相关。

模式变量作用域 = 匹配作用域,锁内匹配变量锁外不可用。并发下注意作用域边界。

#

92. 方法耗时采集与并发,采样对线程执行的影响

方法耗时采集与并发:采样对线程执行的影响是什么?

  • 方法耗时采集
  • 采样
  • 执行影响

方法耗时采集影响并发:1) 埋点(记录时间戳)有开销,热点路径影响性能;2) 采样(JFR/抽样)低开销,不影响执行;3) 全量统计(每个方法)开销大。权衡:采样(低开销、概率)vs 全量(精确、开销大)。并发下采集注意:1) 埋点用廉价操作(时间戳、原子);2) 避免在热点路径做重统计;3) 用采样(JFR)减少干扰。方法耗时采集应低开销,采样优于全量。

耗时采集用采样(JFR 低开销)避免影响执行,热点路径埋点宜廉价。

#

93. 证书加载的并发安全,PKI 缓存与多线程初始化

证书加载的并发安全:PKI 缓存与多线程初始化是什么?

  • 证书加载
  • PKI 缓存
  • 多线程初始化

证书加载并发安全:证书(PKI)加载/缓存被多线程并发使用。策略:1) 懒加载 + volatile/双检缓存(只初始化一次);2) 缓存用并发安全(ConcurrentHashMap);3) 证书不可变(只读)安全共享;4) 初始化失败处理。多线程初始化:证书库懒加载用 DCL/volatile 防重复初始化。证书不可变 + 并发缓存 + 懒加载安全,实现多线程安全加载。

证书不可变 + 并发缓存 + 懒加载(DCL/volatile),多线程安全初始化。

#

94. CPU 时间剖析与并发,区分等待与执行的采样方法

CPU 时间剖析与并发:区分等待与执行的采样方法是什么?

  • CPU 时间剖析
  • 等待 vs 执行
  • 采样

CPU 时间剖析区分"等待"与"执行":1) 采样线程状态(RUNNABLE=执行,BLOCKED/WAITING=等待);2) getThreadCpuTime 测 CPU 时间(执行),getThreadUserTime 区分;3) JFR 采样/线程状态统计。区分方法:看线程时间占比(CPU 时间 vs 阻塞时间),判断是 CPU 密集还是等待瓶颈。并发剖析:CPU 时间高=计算密集,等待时间长=IO/锁/竞争。采样区分等待与执行,定位瓶颈类型。

CPU 时间(执行)vs 阻塞时间(等待)区分瓶颈。getThreadCpuTime + 状态采样。

#

95. JFR 事件与线程 dump 在死锁诊断中的配合

JFR 事件与线程 dump 在死锁诊断中的配合是什么?

  • JFR 事件
  • 线程 dump
  • 死锁诊断

死锁诊断配合:1) 线程 dump 直接显示死锁(Found one Java-level deadlock),提供循环等待链;2) JFR 事件(lock 等待、Active 线程)提供死锁发生的时间线、锁等待时长、线程状态变化;3) 配合:dump 定位死锁结构,JFR 分析死锁成因与触发时间。JFR 记录锁获取/等待事件,dump 快照死锁状态。诊断:dump 确认死锁,JFR 回放历史(多久、怎么陷入)。配合提供完整死锁证据。

dump 显示死锁结构,JFR 提供时间线与成因。配合诊断死锁。

#

96. 并发基准的陷阱,预热不足与锁竞争导致的偏差

并发基准的陷阱:预热不足与锁竞争导致的偏差是什么?

  • 并发基准
  • 预热不足
  • 锁竞争偏差

并发基准陷阱:1) 预热不足:JIT 未编译、类未加载,测出"冷"性能,偏差大;2) 锁竞争:并发度/锁竞争程度未控制,测出结果受竞争影响;3) 伪共享、调度噪声。避免:1) 充分预热(JMH @Warmup);2) 控制并发度与竞争(多线程);3) 多次迭代、多 Fork;4) 用 JMH 规范化。并发基准需预热、控制竞争、多迭代,否则结果偏差。锁竞争要真实模拟(多线程)。

并发基准陷阱:预热不足、锁竞争未控。JMH 预热+控制竞争+多迭代。

#

97. 并发微基准测试的规范,隔离线程数与状态作用域

并发微基准测试的规范:隔离线程数与状态作用域是什么?

  • 微基准
  • 线程数
  • 状态作用域

并发微基准规范:1) 隔离线程数(@Threads 控制并发度,多线程测竞争);2) 状态作用域(@State Scope.Benchmark 共享、Scope.Thread 线程本地,控制共享状态);3) 预热与多迭代;4) 黑盒消费结果。规范要点:线程数隔离(测不同并发度)、状态作用域正确(共享 vs 线程本地)、避免 JIT 优化。并发微基准用 @Threads 与 @State 控制并发与状态,保证可重复。

并发微基准用 @Threads 隔离并发度、@State 控制作用域、预热多迭代。规范保证可重复。

#

98. 火焰图定位并发瓶颈,锁等待与上下文切换的识别

火焰图定位并发瓶颈:锁等待与上下文切换的识别是什么?

  • 火焰图
  • 锁等待
  • 上下文切换

火焰图定位并发瓶颈:1) 火焰图显示 CPU 采样栈(各方法 CPU 占比),CPU 密集瓶颈看宽栈;2) 锁等待:线程在锁点(AbstractQueuedSynchronizer.park、MonitorEnter)的栈宽,表示锁竞争;3) 上下文切换:off-CPU 火焰图(等待栈)显示阻塞/切换,识别 IO/锁等待。识别:CPU 火焰图看计算热点,off-CPU 火焰图看等待/切换。并发瓶颈定位:宽栈=热点,锁/切换栈=竞争。

CPU 火焰图看计算热点,off-CPU 火焰图看等待/切换。锁等待栈宽=竞争。

#

99. 分配剖析与并发,TLAB 竞争在并发应用中的表现

分配剖析与并发:TLAB 竞争在并发应用中的表现是什么?

  • 分配剖析
  • TLAB
  • 竞争

TLAB(Thread Local Allocation Buffer):每线程本地分配缓冲,避免分配竞争。表现:1) 正常:每线程 TLAB 分配,无竞争;2) 竞争:线程数多/大对象导致 TLAB 装满,需要锁/全局分配,竞争增加;3) 分配剖析看 TLAB 重分配频率、GC 分配压力。并发表现:高并发分配多时,TLAB 竞争、GC 分配率上升。优化:减少分配(对象复用、不可变)、控制线程数。分配剖析识别 TLAB 竞争与分配热点。

TLAB 每线程缓冲减少分配竞争,高并发分配多时 TLAB 竞争/GC 压力。分配剖析识别。