锁对象是当前实例(this);即同一对象的多个线程调用该方法时互斥执行,不同对象则互不干扰,等效于synchronized(this)代码块。

synchronized 修饰实例方法时,锁对象是当前实例(this),即同一对象的多个线程调用该方法时会互斥执行,不同对象则互不干扰。
锁的是什么?
当 synchronized 修饰实例方法,JVM 会在方法入口处自动加锁,锁住的是调用该方法的对象实例(this)。也就是说:
- 线程 A 调用
obj1.method(),会尝试获取obj1的内置锁; - 线程 B 同时调用
obj1.method(),必须等待线程 A 释放锁; - 但线程 C 调用
obj2.method()(另一个对象),可立即执行,不受影响。
写法和等效形式
以下两种写法语义完全等价:
- 直接修饰方法:
public synchronized void transfer(int amount) { ... } - 手动同步代码块:
public void transfer(int amount) { synchronized(this) { ... } }
推荐第一种——简洁、意图明确,且锁范围覆盖整个方法体。
注意事项
容易忽略的关键点:
- 静态方法不能靠
this锁,必须用synchronized static,此时锁的是类对象(MyClass.class); - 如果方法内部只操作局部变量或线程私有资源,加 synchronized 是多余的;
- 若需细粒度控制(如只锁某段逻辑),应优先考虑同步代码块,避免无谓阻塞;
- 锁对象不能为 null,否则运行时抛
NullPointerException。
一个典型例子
银行账户取款,防止余额被并发修改:
<font color="blue">class Account {
private double balance;
public Account(double balance) {
this.balance = balance;
}
public synchronized void withdraw(double amount) {
if (balance >= amount) {
balance -= amount; // 非原子操作,必须同步
}
}
public double getBalance() {
return balance;
}
}</font>
两个线程同时对同一个 Account 实例调用 withdraw(),不会出现余额超扣问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











