synchronized 通过原子执行读-改-写操作保护多线程计数器,支持同步方法(锁this)、同步代码块(指定final锁对象)和静态锁(Class或static final对象),而AtomicInteger则基于CAS提供更高性能的无锁累加。

用 synchronized 保护多线程计数器累加,核心是确保每次读-改-写(如 count++)操作**原子执行**,避免多个线程同时读取旧值、各自加1、再写回,导致结果丢失。
同步方法:最简单直接的方式
把累加逻辑封装在 synchronized 修饰的实例方法里。JVM 会自动以当前对象(this)为锁,保证同一时刻只有一个线程能进入该方法。
public class Counter {
private int count = 0;
public synchronized void increment() {
count++; // 等价于 count = count + 1,整个过程被锁保护
}
public int getCount() {
return count;
}
}
✅ 优点:写法简洁,语义清晰。
⚠️ 注意:若多个线程操作的是不同 Counter 实例,锁不共享,无法互斥——此时需用静态同步或显式锁对象。
同步代码块:更灵活,可指定锁对象
当需要细粒度控制(比如只锁累加,不锁其他逻辑),或想让多个实例共用一把锁时,推荐用 synchronized(锁对象) 块。
- 用 同一个对象引用作为锁(如
private final Object lock = new Object();),所有线程竞争这把锁 - 避免用
this或String、常量等可能被外部获取或复用的对象作锁,以防意外干扰 - 锁对象声明为
final,防止被意外替换
public class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
}
静态计数器:必须用类锁(Class 对象)
如果计数器是 static 的,多个实例要共享一个值,就必须用类级别的锁——即 Counter.class 或 static final Object 锁对象。
立即学习“Java免费学习笔记(深入)”;
public class Counter {
private static int count = 0;
private static final Object lock = new Object();
public static void increment() {
synchronized (lock) { // ✅ 用 static 锁对象
count++;
}
}
// ❌ 错误:synchronized static 方法锁的是 Counter.class,
// 虽然可行,但不如显式锁对象直观可控
// public static synchronized void increment() { ... }
}
对比 AtomicInteger:为什么有时不用 synchronized?
AtomicInteger 提供无锁的 CAS(Compare-And-Swap)累加,性能通常更高,且天然线程安全:
public class Counter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // 原子性保证,无需 synchronized
}
}
✅ 适合高并发、低争用场景;
⚠️ 但 synchronized 更通用(可保护任意复杂逻辑,不止是加1),语义更明确,调试也更直观。


















