在分布式时环境通过Redisson分布式锁,根据业务字段对一段逻辑进行加锁,本代码是作为一个单体项目实现类似效果。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockByKey {
private static final Logger log = LoggerFactory.getLogger(ReentrantLockByKey.class);
private final Map<String, ReentrantLock> mutexCache = new ConcurrentHashMap<>();
/**
* 根据业务字段值对执行的内容进行加锁,获取锁失败则直接返回,代表该任务已经在运行
* @param key 加锁的业务字段值
* @param statement 加锁的执行逻辑
*/
public void exec(String key,Runnable statement){
ReentrantLock mutex4key = null;
ReentrantLock mutexInCache;
do{
if(mutex4key != null){
mutex4key.unlock();
}
mutex4key = mutexCache.computeIfAbsent(key,k->new ReentrantLock());
boolean tryLock = mutex4key.tryLock();
if(tryLock){
mutexInCache = mutexCache.get(key);
}else {
log.info("key[{}],任务已执行",key);
return;
}
}while (mutexInCache == null || mutex4key != mutexInCache);
try{
statement.run();
}catch (Exception e){
log.error("任务执行出现异常key:{},错误信息:{}",key,e.getMessage(),e);
throw e;
}finally {
if(mutex4key.getQueueLength() == 0){
mutexCache.remove(key);
}
mutex4key.unlock();
}
}
}