缩小synchronized锁粒度的核心是仅锁定真正共享的代码,选用私有final对象作锁、只包裹临界区、按资源拆分独立锁、慎用嵌套并优先考虑reentrantlock超时控制。

用 synchronized 代码块缩小锁粒度,核心是“只锁真正共享的那几行”,而不是整个方法或一大段逻辑。锁得越短、越专,线程竞争就越少,吞吐量自然越高。
选对锁对象:用私有 final 对象,别碰 this 或 Class
锁对象决定作用范围:
- 用
this→ 所有同步实例方法共用一把锁,互相阻塞 - 用
MyClass.class→ 整个类所有静态同步操作串行执行 - 正确做法:声明一个 private final Object lock = new Object();,只用于保护特定资源
- 如果保护的是某个集合(如
private List<log> logs</log>),且它不会被外部替换,也可直接用logs作锁,但更推荐专用锁对象
只包临界区:把 IO、计算、远程调用全移出去
同步块里只放读写共享变量的代码,其他一律剥离:
- 错误写法:在 synchronized 块里查数据库、解析 JSON、调用 HTTP 接口
- 正确顺序:先做耗时操作获取结果 → 进入同步块更新共享状态(如 put 到缓存 map)→ 出来后再处理日志、通知等
- 示例:缓存加载场景中,“检查 key 是否存在 + 放入新值”这两步加锁就够了,加载数据本身不进同步块
按业务拆锁:不同资源用不同锁,避免一把锁管全场
多个独立资源共用同一把锁,会人为制造等待:
- 订单系统中,订单 A 和订单 B 的状态更新互不影响 → 为每个订单 ID 分配专属锁
- 可用
ConcurrentHashMap<long object></long>配合computeIfAbsent动态创建锁对象:lockMap.computeIfAbsent(orderId, id -> new Object()) - 注意控制锁数量,避免内存泄漏;不用字符串或用户输入作锁(有 intern 冲突和安全风险)
慎用嵌套,优先考虑 ReentrantLock 的 tryLock
多层 synchronized 嵌套容易引发死锁,且难以超时控制:
- 若必须分层保护(如外层锁账户余额、内层锁日志列表),确保各层锁对象完全独立且 final
- 更推荐方案:换成
ReentrantLock,用tryLock(3, TimeUnit.SECONDS)设超时,失败可释放已持锁并回退 - 配合
lockInterruptibly()支持线程中断,比纯 synchronized 更可控
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











