单机锁
适合单体应用,使用Java原生的synchronized关键字
- 优点:原生支持,无需引入依赖,代码少,绝对安全
- 缺点:只在当前JVM进程内有效,集群及分布式失效
@Service
public class OrderService {
// 如果是静态方法锁,用类.class;如果是实例方法锁,用 this 或者定义一个 private final Object lock = new Object();
private final Object lock = new Object();
public void createOrder(String orderId) {
// 1. 尝试获取锁(synchronized 会自动阻塞等待)
synchronized (lock) {
// 2. 进入代码块即获得锁
System.out.println("线程 " + Thread.currentThread().getName() + " 获取了锁,开始执行业务...");
// TODO: 这里写你的核心业务逻辑(如扣库存)
// 3. 业务执行完,自动释放锁(无需手动释放)
}
}
}
分布式锁
分布式环境下,最简单的是使用Redisson框架
- 优点:自动续期(看门狗机制),防止死锁,可重入(同一个线程可以多次获取同一个锁)
- 缺点:引入了依赖,代码稍微复杂
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.27.0</version> <!-- 使用最新稳定版 -->
</dependency>
代码示例
@Service
public class OrderService {
@Autowired
private RedissonClient redissonClient; // 注入 Redisson 客户端
public void createOrder(String orderId) {
// 1. 定义锁的名称(建议带业务前缀,如 "order_lock:")
String lockKey = "order_lock:" + orderId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 2. 尝试加锁,最多等待 100ms,上锁后 10 秒自动解锁(防止死锁)
boolean isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (isLocked) {
// 3. 成功获取锁,执行业务
System.out.println("获取锁成功,执行业务...");
// TODO: 扣减库存等操作
} else {
throw new RuntimeException("获取锁失败,系统繁忙");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("获取锁被中断");
} finally {
// 4. 释放锁
if (lock.isHeldByCurrentThread()) { // 确保是自己加的锁才释放
lock.unlock();
}
}
}
}