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