锁优化核心是“用得少、用得准、用得轻”,需从细粒度锁、读写分离、缩短锁时间、无锁优先四维度实践,兼顾线程安全与高并发性能。

锁优化不是加把锁就完事,关键是在保证线程安全的前提下,让锁“用得少、用得准、用得轻”。高并发编程实战的核心,是把理论机制落到具体瓶颈上——比如秒杀库存扣减慢、缓存读写卡顿、日志聚合吞吐上不去。下面从四个最贴近工程落地的维度展开。
一、锁粒度要细:别一把锁管全场
全局锁(如 synchronized(this) 或锁整个 Map)是并发性能的第一杀手。100 个线程抢同一把锁,99 个都在等。
- 用分段锁替代:像
ConcurrentHashMap在 JDK 7 中按 segment 分 16 把锁,JDK 8 改为 Node 级 CAS + synchronized,本质仍是缩小锁定范围 - 业务层可仿照设计:例如订单表按用户 ID 取模分 32 个逻辑桶,每个桶配独立对象锁:
Object lock = locks[userId % 32] - 避免“锁包装”陷阱:不要把数据库连接、HTTP 客户端这类外部资源包进同步块,它们本就不该被多线程共享
二、读写分离:读多写少场景必上读写锁
配置中心、本地缓存、规则引擎等场景,读操作占比常超 95%。用普通互斥锁会让所有读线程排队,白白浪费并发能力。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 直接用
ReentrantReadWriteLock,读锁可重入且共享,写锁独占 - 注意:读锁未释放时,写线程会阻塞;写锁未释放时,新读线程也会阻塞(默认非公平)
- 慎用“读锁内升级写锁”:它不支持,必须先释放读锁再获取写锁,否则死锁
三、锁时间要短:临界区只留真正共享操作
很多人把耗时操作(如远程调用、JSON 序列化、DB 查询)全塞进同步块,导致锁持有几十毫秒甚至更久。
- 把非共享逻辑提前或延后:先查 DB、组装参数,再进锁更新内存状态;锁内只做
counter--、map.put()这类纳秒级操作 - 避免在锁内打印日志或触发 GC:日志框架可能同步刷盘,GC 会暂停所有线程
- 用 JFR 或 Arthas 观察
synchronized方法的平均持有时间,超过 1ms 就该拆
四、能不用锁就不用锁:优先考虑无锁方案
锁是悲观策略,而现代高并发系统越来越倾向乐观或免锁设计。
- 计数类场景用
AtomicInteger/LongAdder(后者在高竞争下比 Atomic 更快) - 状态流转用 CAS + 循环:如订单状态从 “待支付” → “已支付”,用
compareAndSet替代锁判断 - 读远多于写的集合,考虑
CopyOnWriteArrayList(注意写操作会复制整个数组) - 局部变量、ThreadLocal、栈上分配对象,天然线程私有,根本不需要锁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










