|
|
|
@@ -4,9 +4,12 @@ import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate; |
|
|
|
import org.springframework.data.redis.core.ValueOperations; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
/** |
|
|
|
* RedisLock |
|
|
|
* User: Stormeye |
|
|
|
@@ -29,17 +32,19 @@ public class RedisLock { |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
public boolean lock(String key,String value){ |
|
|
|
if(stringRedisTemplate.opsForValue().setIfAbsent(key,value)){//对应setnx命令 |
|
|
|
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); |
|
|
|
if(operations.setIfAbsent(key,value)){//对应setnx命令 |
|
|
|
operations.set(key, value, 1, TimeUnit.SECONDS); |
|
|
|
//可以成功设置,也就是key不存在 |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
//判断锁超时 - 防止原来的操作异常,没有运行解锁操作 防止死锁 |
|
|
|
String currentValue = stringRedisTemplate.opsForValue().get(key); |
|
|
|
String currentValue = operations.get(key); |
|
|
|
//如果锁过期 |
|
|
|
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){//currentValue不为空且小于当前时间 |
|
|
|
//获取上一个锁的时间value |
|
|
|
String oldValue =stringRedisTemplate.opsForValue().getAndSet(key,value);//对应getset,如果key存在 |
|
|
|
String oldValue =operations.getAndSet(key,value);//对应getset,如果key存在 |
|
|
|
|
|
|
|
//假设两个线程同时进来,key被占用了。获取的值currentValue=A(get取的旧的值肯定是一样的),两个线程的value都是B,key都是K.锁时间已经过期了。 |
|
|
|
//而这里面的getAndSet一次只会一个执行,也就是一个执行之后,上一个的value已经变成了B。只有一个线程获取的上一个值会是A,另一个线程拿到的值是B。 |
|
|
|
|