1. 并发性能与锁竞争分析工程导论

当系统从单线程走向多线程、从单机走向分布式,性能问题往往不再表现为“CPU 不够快”,而是表现为“线程在等锁”。一个接口在压测中 P99 从 20 ms 突然跳到 800 ms,CPU 使用率却只有 30%,磁盘和网络都很空闲——这类现象背后,通常是锁竞争、伪共享、线程池饥饿或临界区过长在作祟。本课程要建立的,正是一套把这类“看不见的等待”变成可测量、可定位、可验证的工程方法。

课程定位:从“调参”到“分析工程”

很多团队处理并发性能问题的方式是经验驱动的:加大线程池、换用无锁队列、把 synchronized 改成 ReentrantLock、调大连接数。这些手段有时有效,但缺乏因果链条,容易在下一个版本回归。本课程把并发性能当作一门分析工程来对待,它包含四个不可分割的环节:

  • 可观测:能采集到锁等待时间、持有时间、竞争次数、线程状态分布等指标,而不是只看吞吐和 CPU。
  • 可归因:能把性能劣化映射到具体的锁对象、临界区代码、线程池或数据结构。
  • 可验证:改动前后有可复现的基准与对照,结论不依赖“感觉变快了”。
  • 可回归:把关键并发指标纳入持续压测,防止优化成果被后续提交悄悄破坏。

换句话说,本课程的目标不是教你记住“用 CAS 比锁快”,而是让你在面对一个真实的慢接口时,能沿着“现象 → 指标 → 热点 → 根因 → 改动 → 复测”的路径独立走完一遍。

核心问题域:锁竞争到底在争什么

锁竞争的本质是串行化。当多个线程必须互斥地进入同一段临界区时,无论临界区多短,只要到达速率超过临界区的服务能力,等待队列就会增长,延迟随之上升。可以用一个简化模型来理解:设临界区平均执行时间为 Tc,单位时间内进入临界区的请求数为 λ,则临界区利用率 ρ = λ × Tc。当 ρ 接近 1 时,排队延迟急剧上升;超过 1 后,等待时间近似线性增长,吞吐不再提升。

例如某缓存刷新逻辑,临界区持锁时间约 200 μs,QPS 为 4000,则 ρ = 4000 × 0.0002 = 0.8,此时平均等待已明显高于临界区本身;若 QPS 升到 6000,ρ = 1.2,锁成为硬瓶颈,吞吐被钉死在约 5000 QPS 附近。这个简单估算能帮你在看监控前就判断“是不是锁的问题”。

围绕这个核心,本课程覆盖的问题域包括:互斥锁与读写锁的竞争形态、自旋与阻塞的取舍、CAS 与 ABA、伪共享与缓存行、内存屏障与可见性、无锁与无等待结构的适用边界、线程池与任务队列的排队行为、以及分布式场景下的锁与一致性开销。

分析工程闭环

把上述问题域串起来,就得到本课程反复使用的工作闭环。它不是线性流程,而是一个带反馈的循环:观测发现异常,归因定位热点,假设提出改动,实验验证效果,最后把有效结论沉淀为回归基线。

并发性能分析工程闭环 ① 观测 延迟/吞吐/锁等待 ② 归因 热点锁/临界区定位 ③ 假设 提出可证伪改动 ④ 实验 对照压测/复现 ⑤ 回归基线 指标入库/持续压测 反馈:新基线触发下一轮观测 关键判据: 锁等待时间占比 > 20% 或 P99 随并发线性上升 → 优先怀疑锁竞争;改动后需在相同负载模型下复测,指标改善且无回归方可沉淀。

这个闭环的关键在于“可证伪”。每一次改动都应附带一个明确预期,例如“把读多写少的 ReentrantLock 换成 StampedLock 乐观读,预期读路径锁等待下降 60%”。如果复测没有达到预期,说明假设有误,需要回到归因环节,而不是继续叠加改动。

工具链概览

不同层次的工具解决不同粒度的问题,本课程会按“先粗后细”的顺序使用它们:

层次典型工具能回答的问题
系统级perf、vmstat、pidstatCPU 花在用户态还是内核态?上下文切换是否异常?
JVM/运行时级async-profiler、JFR、jstack哪些线程在 BLOCKED/WAITING?锁热点在哪个栈帧?
锁与并发原语级JFR 锁事件、perf lock、eBPF具体锁对象的竞争次数、等待时长、持有者
应用级Micrometer、自定义埋点、压测框架业务维度的 P99、队列深度、拒绝率

工具本身不是重点,重点是知道“什么现象该用哪一层工具”。例如看到 CPU 大量消耗在 sys 态且上下文切换飙升,应先怀疑自旋或频繁唤醒,而不是直接去翻业务代码。

学习路线图

后续章节会沿着“原理 → 观测 → 归因 → 优化 → 验证”的路径展开。前期先建立并发原语与内存模型的正确心智模型,理解互斥、可见性、有序性三者的关系;中期进入实战观测,学会用 JFR 和 async-profiler 抓取锁事件与线程状态;后期聚焦典型场景,包括高并发计数器、缓存、连接池、任务队列和分布式锁,每个场景都配套可复现的示例参数与判断依据。

建议在学习过程中准备一个可压测的本地服务,把每章的示例参数实际跑一遍。并发性能的直觉很难只靠阅读建立,亲手看到 P99 随并发上升的曲线,比记住任何结论都更有价值。

最后需要强调:并发优化不是追求“零锁”。锁是保证正确性的工具,真正要消除的是不必要的竞争和过长的临界区。在正确性面前,性能永远是第二位的;本课程所有优化手段,都以不破坏语义正确性为前提。