SpringBoot 中使用Redis分布式锁

 1 /**
 2      * 获取redis的锁
 3      *
 4      * @param key   键
 5      * @param value 值为当前毫秒数+过期时间毫秒数
 6      * @return 返回true/false
 7      */
 8     public boolean lock(String key, String value) {
 9         if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
10             //加锁成功就返回true
11             return true;
12         }
13         //不加下面这个可能出现死锁情况
14         //value为当前时间+超时时间
15         //获取上一个锁的时间,并判断是否小于当前时间,小于就下一步判断,就返回true加锁成功
16         //currentValue=A 这两个线程的value都是B 其中一个线程拿到锁
17         String currentValue = (String) redisTemplate.opsForValue().get(key);
18         //如果锁过期
19         if (!StringUtils.isEmpty(currentValue)
20                 && Long.parseLong(currentValue) < System.currentTimeMillis()) {
21             //存储时间要小于当前时间
22             //出现死锁的另一种情况,当多个线程进来后都没有返回true,接着往下执行,执行代码有先后,而if判断里只有一个线程才能满足条件
23             //oldValue=currentValue
24             //多个线程进来后只有其中一个线程能拿到锁(即oldValue=currentValue),其他的返回false
25             //获取上一个锁的时间
26             String oldValue = (String) redisTemplate.opsForValue().getAndSet(key, value);
27             if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
28                 //上一个时间不为空,并且等于当前时间
29                 return true;
30             }
31 
32         }
33         return false;
34     }
35 
36 
37     /**
38      * redis释放锁
39      *
40      * @param key   键
41      * @param value 值
42      */
43     public void unlock(String key, String value) {
44         //执行删除可能出现异常需要捕获
45         try {
46             String currentValue = (String) redisTemplate.opsForValue().get(key);
47             if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
48                 //如果不为空,就删除锁
49                 redisTemplate.opsForValue().getOperations().delete(key);
50             }
51         } catch (Exception e) {
52             log.error("[redis分布式锁] 解锁", e);
53         }
54     }

 

 

posted @ 2020-04-28 16:39  devin_w_zhang  阅读(297)  评论(0编辑  收藏  举报