Redis锁

package com.luo.spring_vue.controller;​
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RestController;​
import javax.annotation.Resource;​
/**
 * @author  
 * 
 * @desc ...
 *  * @date 2020-12-20 11:10:29
 *  *  *String key A, int expireTime 30 *
 *  * currentTime 1030 * 
 * * valueStr 1030 * 
 * * true * -------- *
 *  * String key B, int expireTime 30 *
 *  * currentTime 2030 *
 *  * valueStr 2030 *
 *  * currentValue 2030 *
 *  * currentValue !=null 2030<3030 * 
 * * oldValue 2030 *
 *  * oldValue!=null oldValue.equals(currentValue) *
 *  * true * --------- *
 *  String key C, int expireTime 30 *
 *  * currentTime 3030 *
 *  * valueStr 3030 *
 *  * currentValue 3030 *
 *  * currentValue !=null 3030<2030(!) *
 *  * false *  
 */
 @RestController
 public class RedisController {    
 @Resource    
 private RedisTemplate redisTemplate;   
  public boolean lock(String key, int expireTime) {        
  long currentTime = System.currentTimeMillis() + expireTime;        
  String valueStr = String.valueOf(currentTime);        
  if (redisTemplate.opsForValue().setIfAbsent(key, valueStr)) { 
   //对应redis原生setnx操作            
   //可以成功设置,也就是key不存在            
   return true;        }        
   //判断锁超时 - 防止原来的操作异常,没有运行解锁操作  防止死锁        
   String currentValue  = (String) redisTemplate.opsForValue().get(key);       
    //如果锁过期       
     if (currentValue !=null&&Long.parseLong(currentValue)<System.currentTimeMillis()) {           
      //获取上一个锁的时间value            
      String oldValue = (String) redisTemplate.opsForValue().getAndSet(key, valueStr);            
      //假设两个线程同时进来这里,因为key被占用了,而且锁过期了。获取的值currentValue=A(get取的旧的值肯定是一样           
       //的),两个线程的value都是B,key都是K.锁时间已经过期了。而这里面的getAndSet一次只会一个执行,也就是一个执行之           
        //后,上一个的value已经变成了B。只有一个线程获取的上一个值会是A,另一个线程拿到的值是B。          
          if (oldValue!=null&&oldValue.equals(currentValue)) {               
           //oldValue不为空且oldValue等于currentValue,也就是校验是不是上个对应的商品时间戳,也是防止并发                
           return true;            }       
            }        
            return false;   
             }   
              public void unlock(String key, String value) {      
                try {            
                String currentValue  = (String) redisTemplate.opsForValue().get(key);            
                if (currentValue!=null&&currentValue.equals(value)) {                
                redisTemplate.delete(key);           
                 }       
                  } 
                  catch (Exception e) { 
                             e.printStackTrace();  
                                   }  
                                     }​}​
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值