通过key上锁,优化 jvm Lock

为什么要减小lock的粒度

jvm的lock对象锁是代码块级别,粒度太大,如果使用redis做锁,对于单体项目来说杀鸡用牛刀!

不多说上代码

代码

这个接口 是用来执行真正的业务

/**
 * 锁函数
 *
 * @author LeiHeng
 */
public interface LockFunction {

    /**
     * 执行方法
     */
    void execute();

}

上锁工具类的接口,之所以用接口,方便以后替换redis做锁

/**
 * 上锁工具类
 *
 * @author LeiHeng
 */
public interface LockUtil {

    /**
     * 上锁
     *
     * @param key          上锁的key
     * @param lockFunction 执行的函数
     * @return 是否上锁成功
     */
    boolean lockAndExecute(String key, LockFunction lockFunction);


}

锁工具类的实现接口

package com.zombies.pixel.business.utils.lock.impl;

import com.zombies.pixel.business.utils.lock.LockFunction;
import com.zombies.pixel.business.utils.lock.LockUtil;
import com.zombies.pixel.common.utils.OptionalTactics;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName: LockUtilImpl
 * @Description: 上锁工具类实现类
 * @author: LeiHeng
 * @date: 2022/6/22 10:45
 */
@Component
@Slf4j
public class LockUtilImpl implements LockUtil {

    /**
     * 锁集合
     */
    private final Map<String, Lock> lockMap = new ConcurrentHashMap<>();


    /**
     * 上锁
     *
     * @param key          上锁的key
     * @param lockFunction 执行的函数
     * @return 是否上锁成功
     */
    @Override
    public boolean lockAndExecute(String key, LockFunction lockFunction) {
        // 获取锁
        Lock lock = getLock(key);
        // 上锁
        lock.lock();
        try {
            // 执行业务
            lockFunction.execute();
            return true;
        } catch (Exception e) {
            log.error("lock service exception , exception is : ", e);
            throw e;
        } finally {
            // 解锁
            lock.unlock();
            log.info("thread is unlock , start remove key");
            // 移除锁信息
            lockMap.remove(key);
        }
    }

   /**
     * 获取锁
     *
     * @param key key
     * @return Lock
     */
    private Lock getLock(String key) {
        // 查询当前key是否存在锁
        Lock lock = lockMap.get(key);
        // 返回锁
        return OptionalTactics
                .of(Objects.nonNull(lock), Lock.class)
                // 如果存在锁 直接返回
                .whenTrue(() -> lock)
                // 不存在创建一把锁添加到map中返回
                .whenFalse(() -> {
                    // 加锁
                    synchronized (key) {
                        // 第二次取
                        Lock doubleCheckLock = lockMap.get(key);
                        // 第二次检查 不存在则创建
                        return OptionalTactics
                                .of(Objects.nonNull(doubleCheckLock), Lock.class)
                                // 如果第二检查的时候,有锁了则返回已经创建的锁
                                .whenTrue(() -> doubleCheckLock)
                                // 第二次检查如果没有锁的化 , 创建锁
                                .whenFalse(() -> {
                                    // 创建新锁
                                    Lock newLock = new ReentrantLock();
                                    // 添加到集合中并且返回
                                    return lockMap.put(key, newLock);
                                })
                                .execute();
                    }
                })
                .execute();
    }

一个小的true或者false的策略模式

package com.zombies.pixel.common.utils;

import com.zombies.pixel.common.enums.BusinessResCode;
import com.zombies.pixel.common.exception.BusinessException;
import lombok.Data;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * @ClassName: OptionalTactics
 * @Description: 一个简单的策略类
 * @author: LeiHeng
 * @date: 2022/6/17 15:41
 */
public class OptionalTactics<R> {

    /**
     * 规则
     */
    private final Boolean rule;

    /**
     * true 所执行的函数
     */
    private Supplier<R> trueFun;

    /**
     * false所执行的函数
     */
    private Supplier<R> falseFun;

    /**
     * 返回值类型
     */
    private final Class<R> resultType;

    /**
     * 构造器
     *
     * @param rule       规则
     * @param resultType 返回值类型
     */
    private OptionalTactics(boolean rule, Class<R> resultType) {
        this.rule = rule;
        this.resultType = resultType;
    }

    /**
     * of 创建optionalTactics类
     *
     * @param rule       规则
     * @param resultType 返回值类型
     * @param <T>        泛型
     * @return 返回optionalTactics类
     */
    public static <T> OptionalTactics<T> of(boolean rule, Class<T> resultType) {
        return new OptionalTactics<>(rule, resultType);
    }

    /**
     * true所执行的函数
     *
     * @param trueFun 执行函数
     * @return 返回optionalTactics类
     */
    public OptionalTactics<R> whenTrue(Supplier<R> trueFun) {
        this.trueFun = trueFun;
        return this;
    }

    /**
     * false所执行的函数
     *
     * @param falseFun 执行函数
     * @return 返回optionalTactics类
     */
    public OptionalTactics<R> whenFalse(Supplier<R> falseFun) {
        this.falseFun = falseFun;
        return this;
    }

    /**
     * 执行
     *
     * @return 返回true或者false执行后的值
     */
    public R execute() {
        return rule ?
                Optional
                        .ofNullable(trueFun)
                        .orElseThrow(() -> new RuntimeException( "true fun is null"))
                        .get()
                :
                Optional
                        .ofNullable(falseFun)
                        .orElseThrow(() -> new RuntimeException("false fun is null"))
                        .get();
    }

}

欢迎大家讨论,并且指出不足!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值