在分布式系统的业务场景中,当多个服务实例需要操作共享变量时,通常需要借助Redisson分布式锁来保证并发安全。传统的加锁逻辑需要手动调用加锁、释放锁方法,还要处理异常场景下的锁释放,代码冗余且容易出现遗漏。利用Lambda表达式可以封装加锁逻辑,让业务代码更简洁,同时规避锁相关的问题。

传统Redisson变量加锁逻辑的问题
传统的Redisson分布式锁操作共享变量的代码通常如下,需要手动处理加锁、释放锁和异常:
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class TraditionalLockDemo {
private RedissonClient redissonClient;
private int sharedVariable = 0;
public void updateVariable() {
String lockKey = "variable_lock_key";
RLock lock = redissonClient.getLock(lockKey);
boolean isLocked = false;
try {
// 尝试加锁,等待3秒,锁过期时间10秒
isLocked = lock.tryLock(3, 10, TimeUnit.SECONDS);
if (isLocked) {
// 操作共享变量
sharedVariable += 1;
System.out.println("当前共享变量值:" + sharedVariable);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
} finally {
// 只有加锁成功才释放锁
if (isLocked && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
这种写法存在几个明显问题:
- 每次操作共享变量都要重复编写加锁、释放锁的模板代码,冗余度高
- 如果开发人员忘记在finally中释放锁,或者释放锁的逻辑写错,会导致锁泄露
- 加锁参数、异常处理逻辑分散在各个业务方法中,后续修改成本高
Lambda表达式优化思路
我们可以定义一个函数式接口,将需要加锁执行的业务逻辑封装为Lambda表达式,再通过一个统一的工具类来处理加锁、释放锁和异常逻辑。这样业务方只需要关注自身的业务逻辑,不需要关心锁的操作细节。
定义函数式接口
首先定义一个无参数、无返回值的函数式接口,用于承载加锁后执行的逻辑:
@FunctionalInterface
public interface LockExecuteLogic {
/**
* 加锁后执行的逻辑
*/
void execute();
}
封装Redisson锁工具类
封装一个工具类,提供统一的加锁执行方法,内部处理所有锁相关的操作:
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class RedissonLockHelper {
private RedissonClient redissonClient;
public RedissonLockHelper(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
/**
* 执行带锁的业务逻辑
* @param lockKey 锁的key
* @param waitTime 等待加锁时间,单位秒
* @param leaseTime 锁过期时间,单位秒
* @param logic 加锁后执行的逻辑,用Lambda表达式传入
*/
public void executeWithLock(String lockKey, long waitTime, long leaseTime, LockExecuteLogic logic) {
RLock lock = redissonClient.getLock(lockKey);
boolean isLocked = false;
try {
isLocked = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
if (isLocked) {
// 执行传入的Lambda逻辑
logic.execute();
} else {
System.out.println("获取锁失败,锁key:" + lockKey);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
} finally {
if (isLocked && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
优化后的变量加锁实战示例
使用封装好的工具类,操作共享变量的代码可以大幅简化:
public class OptimizedLockDemo {
private RedissonLockHelper lockHelper;
private int sharedVariable = 0;
public OptimizedLockDemo(RedissonLockHelper lockHelper) {
this.lockHelper = lockHelper;
}
public void updateVariable() {
String lockKey = "variable_lock_key";
// 传入锁参数和业务逻辑Lambda,无需关心加锁释放细节
lockHelper.executeWithLock(lockKey, 3, 10, () -> {
sharedVariable += 1;
System.out.println("当前共享变量值:" + sharedVariable);
});
}
}
如果需要操作带返回值的业务逻辑,可以再定义一个带返回值的函数式接口和对应的工具方法:
@FunctionalInterface
public interface LockExecuteLogicWithResult<T> {
T execute();
}
public class RedissonLockHelper {
// 之前的代码省略
public <T> T executeWithLockAndResult(String lockKey, long waitTime, long leaseTime, LockExecuteLogicWithResult<T> logic) {
RLock lock = redissonClient.getLock(lockKey);
boolean isLocked = false;
try {
isLocked = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
if (isLocked) {
return logic.execute();
}
return null;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
return null;
} finally {
if (isLocked && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
优化方案的优势
- 代码复用性高:所有加锁的模板逻辑都封装在工具类中,业务代码不再重复编写
- 安全性强:锁的释放逻辑统一处理,避免了开发人员遗漏释放锁导致的锁泄露问题
- 可维护性高:加锁参数、超时时间等配置集中在工具类管理,后续修改只需要调整工具类即可
- 可读性好:业务代码只保留核心逻辑,结构更清晰,降低理解成本
这种基于Lambda表达式的优化方式适用于所有需要Redisson分布式锁操作共享变量的场景,能够有效提升代码质量和开发效率。