Controller控制并发锁解决方案

2022-01-25  本文已影响0人  阳光也学会了妩媚

问题描述

针对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,()->{
                //执行代码

        });
上一篇下一篇

猜你喜欢

热点阅读