synchronized是Java基础同步机制,通过加锁实现临界区串行化:修饰实例方法锁this、静态方法锁Class对象、代码块可自定义锁对象,且为可重入锁,异常时自动释放。

synchronized 是 Java 中最基础的同步机制,用于保证同一时刻只有一个线程能执行被它保护的代码,从而避免多线程并发访问共享资源时出现数据不一致问题。它的核心作用就是“加锁”,让临界区串行化执行。
修饰实例方法:锁的是当前对象(this)
当用 synchronized 修饰普通成员方法时,JVM 会自动以调用该方法的对象(即 this)作为锁对象:
- 多个线程调用同一个对象的 synchronized 实例方法,会被阻塞排队执行;
- 但不同对象的 synchronized 实例方法可以并行执行(因为锁对象不同);
- 注意:静态方法不能用 this 锁,要用类对象锁(见下一条)。
示例:
public class Counter {
private int count = 0;
public synchronized void increment() { // 等价于 synchronized(this)
count++;
}
}
修饰静态方法:锁的是类对象(Class)
静态方法属于类,没有 this,所以 synchronized 静态方法实际是以 当前类的 Class 对象(如 Counter.class)为锁:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 所有线程调用该类的任意 synchronized 静态方法,都共用同一把锁;
- 它和 synchronized 实例方法互不干扰(锁对象不同),可同时执行;
- 适合控制整个类级别的共享资源,比如单例初始化、全局计数器等。
示例:
public class Counter {
private static int totalCount = 0;
public static synchronized void addTotal() { // 等价于 synchronized(Counter.class)
totalCount++;
}
}
修饰代码块:显式指定锁对象,更灵活精准
用 synchronized(锁对象) 包裹一段代码,称为同步代码块。这是最推荐的方式,因为:
- 可以只锁定真正需要保护的临界区,减少锁粒度,提升并发性能;
- 能自由选择锁对象(可以是 private final Object lock = new Object();),避免意外暴露锁;
- 不会像同步方法那样锁住整个方法体,尤其适合方法体中只有部分逻辑需同步的情况。
示例:
public class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
// 其他非临界操作...
synchronized(lock) { // 只锁这一小段
count++;
}
// 其他非临界操作...
}
}
注意事项和常见误区
使用 synchronized 要特别留意以下几点:
-
锁对象不能为空:如果锁对象为 null,运行时抛
NullPointerException; - 不可重入?错!synchronized 是可重入锁:同一线程可多次进入自己已持有的锁,不会死锁;
- 锁的是对象,不是代码或方法名:两个 synchronized 方法若锁不同对象,就互不影响;
-
不要用 String 或常量池对象作锁:容易被外部误用导致锁冲突(如
synchronized("abc")); - 异常不会破坏锁释放:无论正常退出还是抛异常,JVM 都会自动释放锁(基于 monitorexit 字节码)。

















