问题描述
针对Controller接收消息处理,过程中非常多涉及数据并发访问,造成代码重复执行的问题,比如微信支付等返回数据处理问题。
解决方式:
最直接的方式,就是直接一把锁搞定,即便多个请求进来都要顺序排队。但这种方式会造成系统瓶颈,是否可以有一种方案,可以根据访问对象的ID或其他唯一标识进行加锁处理,从而达到最理想的效果。
工具如下:
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by SunYuechao on 2022/1/24 下午11:57
* 同步锁,工具类,经典锁工具,可根据对象对controller 进行线程控制,比如根据订单进行 线程控制
*/
@Component
public class SynchronizedControllerByKey {
Map<String, ReentrantLock> mutexCache = new ConcurrentHashMap<>();
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());
mutex4Key.lock();
mutexInCache = mutexCache.get(key);
/**
* 两种极端情况
* 1、mutexInCache==null 拿到这把锁被remove掉了
* 2、mutexInCache!=mutex4Key 不是同一把锁
*/
}while (mutexInCache==null || mutexInCache != mutex4Key);
try {
statement.run();
} finally {
//没有排队就
if (mutex4Key.getQueueLength() == 0) {
mutexCache.remove(key);
}
mutex4Key.unlock();
}
}
}
使用方法:
//引入
@Autowired
SynchronizedControllerByKey synchronizedControllerByKey;
//使用
synchronizedByKey.exec(key,()->{
//执行代码
});
网友评论