synchronized设计线程安全计数器需选对锁对象并匹配生命周期:实例级用同步方法(锁this),多实例独立计数;需细粒度控制时用同步代码块(锁final对象);全局共享用静态同步方法(锁Counter.class);volatile无法保证count++原子性,synchronized兼顾原子性与可见性。

用 synchronized 设计线程安全的计数器,核心是确保“读-改-写”操作(比如 count++)在多线程下原子执行,不被其他线程打断。它不是给变量加个关键字就行,而是要选对锁对象、控制好同步范围,并匹配计数器的生命周期(实例级 or 类级别)。
用同步方法保护实例级计数器
适合每个对象维护独立计数值的场景,比如多个订单服务各自统计处理次数。
- 直接在实例方法上加
synchronized,锁对象是当前实例(this) - 所有对该实例的调用都会串行执行,保证
count++不丢失 - 注意:不同实例之间互不影响——如果误以为“所有计数器都共享”,就达不到全局累加效果
示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
public class Counter {
private int count = 0;
public synchronized void increment() {
count++; // 整个方法体受 this 锁保护
}
public int getCount() { return count; }
}
立即学习“Java免费学习笔记(深入)”;
用同步代码块控制锁粒度
当方法里还有其他非临界逻辑,或想让多个实例共用一把锁时,比同步方法更灵活。
- 声明一个私有
final Object lock = new Object();作为锁对象 - 只把
count++包进synchronized(lock)块中,避免无关代码被阻塞 - 锁对象必须是
final,防止被替换导致锁失效;不能用this、字符串字面量或常量,以防外部意外争用
示例:
public class Counter {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized(lock) {
count++;
}
}
}
用静态同步方法实现全局计数器
当需要所有实例共享同一个计数值(如系统总请求次数),必须升级到类级别锁。
- 把计数器字段和方法都声明为
static,再加synchronized - 此时锁对象是
Counter.class,所有线程无论通过哪个实例调用,都竞争同一把锁 - 不要混用:静态方法和实例方法用的是不同锁,彼此不互斥
示例:
public class Counter {
private static int count = 0;
public static synchronized void increment() {
count++;
}
public static int getCount() { return count; }
}
补充说明:为什么不用 volatile 或普通变量
volatile 只能保证可见性,不能解决 count++ 的原子性问题——它仍会被拆成“读值→+1→写回”三步,两个线程可能同时读到 5,各自加 1 后都写回 6,结果丢失一次累加。
而 synchronized 不仅强制串行执行,还保障了锁释放前的修改对下一个获取锁的线程立即可见,天然兼顾原子性与可见性。
如果只是做简单计数,AtomicInteger 是更轻量高效的选择;但若后续要扩展为带条件判断、复合更新等复杂逻辑,synchronized 提供的临界区控制能力更清晰可控。

















