JAVA-求大佬帮忙看一下这段锁的代码有改进方向嘛(跪谢)

28 阅读1分钟

希望大佬们帮忙看下代码有没有大的问题,寻求改进的方向,代码的具体业务逻辑不便粘贴,望谅解(磕头)

[!NOTE]

目前代码日志打印有问题

代码逻辑

  • 请求逻辑:查询信息,若没有则创建返回
  • 并发逻辑:
    1. 查询数据,有则返回,无则往下
    2. 获取不到锁,等待 0.2 秒继续第 1 步
    3. 获取到锁,查询是否有数据,无则添加,完成后释放锁
BaseLockWithData 基类
/**
 * 用于处理先查询数据是否存在,不存在则创建的并发问题的分布式锁用到的类
 */
@Data
public class BaseLockWithData<A, S, R> {
    /**
     * 事务名称
     */
    private String txName;
    /**
     * redis的key
     */
    private String key;
    /**
     * redis的锁的时间(秒)
     */
    private long lockTime;
    /**
     * 超时时间(秒)
     */
    private long timeout;
    /**
     * 添加函数的入参
     */
    private A addObj;
    /**
     * 查询函数的参数
     */
    private S searchObj;
    /**
     * 添加函数
     */
    private Function<A, R> addFunction;

    /**
     * 查询函数
     */
    private Function<S, R> searchFunction;

    public void setAddFunction(Function<A, R> addFunction, A addObj) {
        this.addFunction = addFunction;
        this.addObj = addObj;
    }

    public void setSearchFunction(Function<S, R> searchFunction, S searchObj) {
        this.searchFunction = searchFunction;
        this.searchObj = searchObj;
    }

    public BaseLockWithData() {
        this.lockTime = 5;
        this.timeout = 10;
    }
}
具体的锁方法
public <A, S, R> R lockWithData(BaseLockWithData<A, S, R> lockData) {
    R data = null;
    long timeout = lockData.getTimeout() * 1000;
    long startTime = Instant.now().toEpochMilli();
    try {
        // 获取不到锁则循环获取
        while (Instant.now().toEpochMilli() - startTime < timeout) {
            data = lockData.getSearchFunction().apply(lockData.getSearchObj());
            if (data != null) {
                break;
            }
            // 添加分布式锁
            boolean lock = this.lock(lockData.getKey(), lockData.getLockTime());
            if (lock) {
                TransactionStatus transaction = null;
                try {
                    // 控制添加数据数据的事务
                    DefaultTransactionDefinition dtd = new DefaultTransactionDefinition();
                    dtd.setName(lockData.getTxName());
                    transaction = this.transactionManager.getTransaction(dtd);
                    // 防止获取锁的过程中其他线程已经添加好数据
                    data = lockData.getSearchFunction().apply(lockData.getSearchObj());
                    if (data != null) {
                        break;
                    }
                    data = lockData.getAddFunction().apply(lockData.getAddObj());
                    this.transactionManager.commit(transaction);
                } catch (Exception e) {
                    if (transaction != null) {
                        this.transactionManager.rollback(transaction);
                    }
                    log.error("事务[{}]错误:错误信息{}", lockData.getTxName(), e.getMessage(), e);
                    throw new CrmException(RespCodeEnum.SYSTEM_ERROR);
                } finally {
                    this.unlock(lockData.getKey());
                }
            }
            LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100));
        }
    } catch (Exception e) {
        log.info("分布式锁出先问题: {}", e.getMessage(), e);
        throw e;
    }
    if (data == null) {
        log.error("未能在指定时间内获取锁或找到数据,锁键:{}, 超时时间:{}ms", lockData.getKey(), timeout);
        throw new CrmException(RespCodeEnum.REDIS_LOCK_TIMEOUT);
    }
    return data;
}