synchronized同步代码块通过锁对象实现线程互斥,语法为synchronized(锁对象){...},锁必须是非null引用类型;推荐使用private final object lock,避免用this或字符串常量作锁,同步块应尽量精简。

synchronized 同步代码块用于限制多个线程对共享资源的并发访问,确保同一时刻只有一个线程执行该段代码。它的核心是“锁对象”,不是方法或类本身。
同步代码块的基本语法
格式为:synchronized(锁对象) { ... },括号内必须是一个引用类型的变量(不能是基本类型或 null),大括号内是要保护的临界区代码。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 锁对象可以是任意对象,常用
this、类的 Class 对象(MyClass.class)、或专门创建的私有 final 对象(推荐) - 多个线程若使用同一个锁对象进入 synchronized 块,就会互斥执行;用不同锁对象则互不影响
常见锁对象选择与对比
选错锁对象会导致同步失效或过度串行化:
-
this:适用于非静态方法中保护当前实例状态,但外部代码可能拿到 this 并加锁,存在干扰风险 -
MyClass.class:全局唯一,适合保护静态资源或整个类级别的状态,但会阻塞所有同类实例的操作 -
private final Object lock = new Object();:最安全推荐方式,锁作用域明确、不可被外部访问,避免意外竞争
实际使用示例
比如银行账户转账,防止余额被并发修改:
public class Account {
private double balance;
private final Object lock = new Object();
public void transfer(Account target, double amount) {
// 为避免死锁,按对象哈希值顺序加锁
Object firstLock = System.identityHashCode(this) = amount) {
this.balance -= amount;
target.balance += amount;
}
}
}
}
}
- 这里用了两个 synchronized 块嵌套,并按固定顺序获取锁,防止死锁
- 锁对象是
this和target实例,保证两个账户余额更新的原子性
注意事项
- 同步块尽量小:只包裹真正需要保护的代码,减少线程等待时间
- 不要在 synchronized 块中调用外部可变对象的方法(如
list.toString()),可能引发锁外抛异常或死锁 - 锁对象一旦确定,就不能被重新赋值(尤其用
final修饰);也不能用字符串常量或 Integer 等可能被池化的对象作锁 - 同步块不会自动处理业务逻辑的正确性,比如检查余额是否足够仍需在块内完成
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










