Spring Boot3 Synchronized 项目地址
https://gitee.com/supervol/loong-springboot-study
(记得给个start,感谢)
Synchronized 概述
在 Spring Boot 3 应用中,synchronized
作为 Java 原生的线程同步机制,是实现本地锁(仅在当前 JVM 进程内生效)的基础工具,用于解决单实例应用中的并发安全问题。
Synchronized 核心
synchronized
是Java 的关键字,其核心作用是保证同一时刻只有一个线程执行特定代码块,从而避免多线程并发访问共享资源时出现的数据不一致(如脏读、重复修改等)问题。在 Spring Boot 3 中,它的本质是本地锁:仅对当前 JVM 进程内的线程有效,无法跨进程(如分布式部署的多实例应用)同步,这是与分布式锁(如 Redis 锁、ZooKeeper 锁)的核心区别。
Synchronized 使用
在 Spring Boot 3 中,synchronized
的使用方式与标准 Java 一致,主要有以下 3 种:
1. 修饰实例方法
锁对象为当前对象实例(this
),即多个线程调用同一对象的该方法时会被同步。
@Service
public class StockService {
private int stock = 100; // 共享资源
// 修饰实例方法:锁为当前StockService实例(单例Bean时全局有效)
public synchronized void deductStock() {
if (stock > 0) {
stock--;
System.out.println("扣减成功,剩余库存:" + stock);
} else {
System.out.println("库存不足");
}
}
}
注:Spring Boot 默认 Bean 为单例,因此该锁对所有调用该 Bean 的线程生效。
2. 修饰静态方法
锁对象为当前类的 Class 对象(如StockService.class
),作用范围是整个类,即使多个实例也会被同步。
@Service
public class CounterService {
private static int count = 0; // 静态共享资源
// 修饰静态方法:锁为CounterService.class
public static synchronized void increment() {
count++;
System.out.println("计数:" + count);
}
}
3. 修饰代码块
显式指定锁对象(可自定义),灵活性更高,能缩小同步范围以提升性能。
@Service
public class OrderService {
private final Object lock = new Object(); // 自定义锁对象
private int orderId = 0;
public void createOrder() {
// 仅同步关键代码块,锁为lock对象
synchronized (lock) {
orderId++;
System.out.println("生成订单ID:" + orderId);
}
// 非关键代码(如日志、参数校验)无需同步,提升效率
System.out.println("订单创建完成");
}
}
Synchronized示例
请参考项目地址中 springboot-lock/springboot-local-lock 模块代码。
Synchronized 原理
synchronized
的底层依赖 JVM 的对象监视器(Monitor) 机制,通过修改对象头中的Mark Word
(存储锁状态)实现锁的获取与释放:
- 当线程进入
synchronized
代码块时,会尝试获取锁对象的 Monitor,若成功则独占锁; - 其他线程会被阻塞并进入等待队列,直到持有锁的线程释放 Monitor(退出代码块)。
Java 6 及以上对synchronized
进行了优化,引入了锁升级机制(偏向锁 → 轻量级锁 → 重量级锁),大幅提升了低并发场景下的性能:
- 偏向锁:无竞争时,仅记录线程 ID,几乎无开销;
- 轻量级锁:轻度竞争时,通过 CAS(比较并交换)尝试获取锁,避免线程阻塞;
- 重量级锁:重度竞争时,依赖操作系统互斥量实现,会导致线程阻塞(开销较大)。
Synchronized 场景
synchronized
适用于单实例 Spring Boot 应用,解决以下并发问题:
- 共享资源修改:如库存扣减、计数器累加、订单 ID 生成等;
- 临界区代码保护:如防止多线程同时执行初始化操作(如加载配置);
- 避免重复处理:如防止同一请求被多个线程重复处理(需配合幂等设计)。
Synchronized 注意
- 仅支持本地锁:多实例部署(分布式系统)时,
synchronized
无法跨 JVM 同步,需使用分布式锁(如 Redisson、Curator); - 锁粒度问题:同步范围过大(如修饰整个方法)可能导致性能下降,建议用代码块缩小范围;
- Bean 作用域影响:若 Spring Bean 为原型(
prototype
),实例方法的synchronized
锁仅对当前实例有效,可能无法实现全局同步(需改用静态方法或类锁); - 不可中断性:持有锁的线程若阻塞(如 IO 操作),其他线程会一直等待,可考虑
ReentrantLock
(支持中断)作为替代。
总结
synchronized
是 Spring Boot 3 单实例应用中实现线程安全的简单有效工具,通过原生 Java 机制保证本地并发安全,适合低至中并发场景。但在分布式环境或需要更灵活锁控制(如超时、中断)的场景中,需结合其他同步方案(如分布式锁、ReentrantLock
)使用。