synchronized 锁对象必须是共享的同一实例,实例方法锁 this、静态方法锁 class 对象,同步块宜用私有 final object;应缩小同步范围,只保护关键代码;注意可重入性但避免滥用;对象锁与类锁不可混用。

明确锁对象,避免“锁错人”
使用 synchronized 的核心不是加锁动作本身,而是锁住谁。锁对象必须是多个线程真正共享的同一个实例,否则形同虚设。
- 修饰实例方法时,锁的是 this —— 仅对同一对象实例有效;不同对象的线程互不干扰
- 修饰静态方法时,锁的是 当前类的 Class 对象 —— 所有该类的实例和静态调用都受同一把锁约束
- 同步代码块中,推荐显式声明一个 private final Object lock = new Object() 作为锁,避免意外暴露或被外部误锁(比如用
this或公共字段当锁) - 切忌用字符串字面量(如
synchronized("key"))或可变对象(如Integer、String)作锁,容易因字符串常量池或自动装箱导致锁对象不唯一
缩小同步范围,只锁“关键几行”
整个方法加锁最简单,但性能代价高。多数场景下,共享资源只占方法中一小段逻辑,其余部分完全可以并发执行。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 把耗时操作(如日志打印、网络请求、IO读写)移出同步块,只包裹真正修改共享状态的代码
- 例如:先校验库存是否充足(非同步),再进同步块扣减库存并更新数据库状态
- 对比:
synchronized void update() { ... }vsvoid update() { ...; synchronized(lock) { doCriticalUpdate(); } ...; }
注意可重入性,但别依赖它掩盖设计缺陷
synchronized 是可重入锁,同一个线程可以多次获取同一把锁而不死锁。这是安全特性,不是鼓励嵌套滥用。
- 合理场景:A 方法加锁后调用内部同样需要同步的 B 方法,无需额外解锁再加锁
- 危险信号:方法内层层调用多个
synchronized方法,可能掩盖粒度不合理、职责过重的问题 - 若发现频繁出现“自己锁自己”,应审视是否该拆分逻辑、引入更细粒度锁,或改用
ReentrantLock配合条件变量
区分对象锁与类锁,按需选择作用域
对象锁保护实例状态,类锁保护静态资源或全局配置。混用会导致同步失效或过度阻塞。
- 计数器累加单个用户行为 → 用对象锁(每个用户独立计数)
- 系统总请求数统计、配置热加载开关 → 用类锁或静态同步方法
- 不要用实例方法同步去保护静态变量,也不要用静态同步方法去控制不同对象各自的业务状态
- 一个典型反例:
public static synchronized void init() { ... }和public synchronized void doWork() { ... }同时存在,但两者锁对象不同,无法形成串行保护关系
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










