利用Redis做多线程的锁(RedisLock)

1.前言

由于水平有限,总觉得哪里怪怪的。还请高手批评指正。

2.核心思想

当redis中,有这个key的时候,就认为已经有了锁;业务处理完后,清除redis中key,即认为清除了释放锁。

3.主要应用场景

当两个客户端同时操作一个资源时,客户端1需要审批该资源;客户端2需要撤回该资源。

4.关键源码所示

a)RedisLock.java

package com.wayne.demo.lock;

import com.wayne.demo.dao.RedisDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class RedisLock implements Lock {

    @Autowired
    private RedisDao redisDao;

    //标识当前key有没有被上锁
    private static Map lockedMap = new HashMap<>();

    @Override
    public boolean tryLock(String key) {
        synchronized (key){
            Object o = redisDao.get(0, key);
            if(null != o){
                return false;
            }else{
                return true;
            }
        }
    }

    @Override
    public void lock(String key) {
        synchronized (key){
            redisDao.save(0,key,key);
            lockedMap.put(key,true);
        }
    }

    @Override
    public void unlock(String key) {
        synchronized (key){
            redisDao.removeData(0,key);
            lockedMap.put(key,false);
            lockedMap.remove(key);
        }
    }

    @Override
    public boolean isLocked(String key) {
        return lockedMap.get(key) == null?false:lockedMap.get(key);
    }
}

b)ThreadController.java

package com.wayne.demo.comtrollor;

import com.wayne.demo.lock.RedisLock;
import com.wayne.demo.params.BaseParams;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/threadController")
public class ThreadController {

    private static Logger logger = LoggerFactory.getLogger(ThreadController.class);

    @Autowired
    private RedisLock redisLock;

    @PostMapping("/submitApproval")
    void submitApproval(@RequestBody BaseParams params){
        logger.info("某个线程提交了审核");
        logger.info("我开始处理审核");


        if(!redisLock.isLocked(params.getKey())){
            logger.info("其他资源没有占用");
            logger.info("我开始处理审核");
            redisLock.lock(params.getKey());

            try {
                TimeUnit.MINUTES.sleep(10);
            }catch (InterruptedException e){
               e.printStackTrace();
            } finally {
                redisLock.unlock(params.getKey());
            }
        }else{
            logger.info("其他资源正在处理");
            logger.info("我无法处理审核");
        }
    }

    @PostMapping("/cancelAppral")
    void cancelAppral(@RequestBody BaseParams params){
        logger.info("某个线程撤销了审核");

        if(!redisLock.isLocked(params.getKey())){
            logger.info("其他资源没有占用");
            logger.info("我开始处理撤销了审核");
            redisLock.lock(params.getKey());

            try {
                TimeUnit.MINUTES.sleep(5);
            }catch (InterruptedException e){
                e.printStackTrace();
            } finally {
                redisLock.unlock(params.getKey());
            }

        }else{
            logger.info("其他资源正在处理");
            logger.info("我无法处理撤销了审核");
        }
    }
}

5.测试结果

利用Redis做多线程的锁(RedisLock)_第1张图片

你可能感兴趣的:(Java语言相关,redis)