赞
踩
分布式锁中我们设置的过期时间:
如果有一个线程获取锁之后在进行操作时,到达了锁的过期时间,之后就会有别的线程获得锁,如果这时,第一个线程执行完成后释放锁,就会将第二个锁的线程删除
针对这个情况如何改进:
改进分布式锁添加释放锁的判断
public class SimpleRedisLock implements ILock{ private String name; private StringRedisTemplate stringRedisTemplate; public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) { this.name = name; this.stringRedisTemplate = stringRedisTemplate; } private static final String key_prefix="lock:"; private static final String id_prefix= UUID.randomUUID().toString()+"-"; @Override public boolean tryLock(long timeoutSec) { //获取线程的标识 String threadId= id_prefix+Thread.currentThread().getId(); Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(key_prefix + name, threadId, timeoutSec, TimeUnit.SECONDS); //自动拆箱的返回 return Boolean.TRUE.equals(aBoolean); } @Override public void unlock() { //获取线程标识 String threadid = id_prefix + Thread.currentThread().getId(); //获取锁中的标识 String s = stringRedisTemplate.opsForValue().get(key_prefix + name); //判断标识是否一致 if(threadid.equals(s)) { //释放锁 stringRedisTemplate.delete(key_prefix+name); } } }
上述我们做了修改进行判断,但是还存在一种极端情况,当线程操作完毕需要释放锁的时候,这个时候已经判断完毕,但是由于比如说垃圾回收等问题对线程的释放操作进行阻塞,这个时候如果超过等待时间,这是还是会出现上述问题,在阻塞结束之后,会删除其他线程的锁
要彻底避免这种情况的发生,需要将判断锁标识的动作与释放锁标识的动作进行原子性操作,此时就会用到Lua脚本
Redis提供了Lua脚本功能,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性,Lua脚本时一种编程语言
地址:https://www.runoob.com/lua/lua-tutorial.html
编写Lua脚本
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by LENOVO.
--- DateTime: 2024/4/26 19:01
---比较线程标识与锁中的标识是否一致
if(redis.call('get',KEY[1]) == ARGV[1]) then
--- 释放锁资源
return redis.call('del',KEY[1])
end
return 0
调用Lua脚本:
@Override
public void unlock() {
//调用lua脚本
stringRedisTemplate.execute(
UNLOCK_SCRIPT,
Collections.singletonList(key_prefix+name),
id_prefix+Thread.currentThread().getId());
}
其中的UNLOCK_SCRIPT
是脚本对象,需要提前进行定义
//设置脚本对象
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
static{
UNLOCK_SCRIPT =new DefaultRedisScript<>();
UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
UNLOCK_SCRIPT.setResultType(Long.class);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。