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 }