优化高频同步代码块的核心是让锁更轻、更准、更少争抢:缩小同步范围至真正共享的临界区,使用私有final锁对象替代this或Class,多锁按固定顺序(如hashCode升序)获取以防死锁。

高频同步代码块容易成为性能瓶颈,优化核心不是“去掉锁”,而是让锁更轻、更准、更少争抢。
缩小同步范围,只锁真正共享的临界区
避免把日志打印、参数校验、IO调用等非共享操作包进 synchronized 块里。这些操作不涉及共享变量,却白白拖长持锁时间,增加线程排队概率。
推荐做法:
- 把纯本地计算、对象创建、字符串拼接等移出同步块
- 同步块内只保留读写共享字段、修改共享集合、更新状态标志等必要操作
- 例如转账逻辑中,只需锁余额变更部分,而非整个 transfer() 方法体
用专用 final 锁对象替代 this 或 Class
用 this 作锁会导致所有同步实例方法互相阻塞;用 类.class 更是让全类静态同步方法全局串行。高频场景下,它们锁粒度太粗,极易引发线程饥饿。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
正确做法:
- 声明私有 final Object lock = new Object(); 作为专属锁
- 多个相关方法统一使用该 lock,确保同步语义一致又不干扰其他业务
- 绝对避免用字符串字面量(如 synchronized("LOCK"))或 Integer 等常量池对象——它们可能被无关模块意外复用,导致隐蔽串行
按固定顺序加多把锁,预防死锁并提升吞吐
当一个操作需同时锁多个对象(如账户 A 和 B 的余额),若线程 1 先锁 A 再锁 B,线程 2 反过来先锁 B 再锁 A,就可能死锁。
安全策略:
- 约定统一加锁顺序,比如按对象 hashCode() 升序获取:if (a.hashCode()
- 对同类资源(如多个 Account 实例)可引入唯一 ID 字段,按 ID 排序加锁,比 hashCode 更稳定
- 尽量减少嵌套锁层级,单次操作一把锁最优;必须多锁时,优先考虑是否能合并为一个更高层的锁对象
关注锁升级状态,必要时关闭偏向锁
在高并发、多线程频繁切换竞争的场景下,偏向锁不仅没收益,反而因撤销开销带来额外负担。JVM 默认开启偏向锁,但高频同步代码块往往属于“强竞争”模式。
可选动作:
- 用 -XX:-UseBiasedLocking 启动参数关闭偏向锁,让锁直接从轻量级起步
- 通过 jstat -compiler 或 JFR(Java Flight Recorder)观察 biased_locking 撤销次数,若频繁发生,说明偏向锁已失效
- 注意:关闭偏向锁对低竞争场景可能略增开销,应结合压测数据判断

















