单实例的分布式锁:
加锁-设计思路是通过setnx命令(只有key不存中才可以加锁)给key设置一个value值(用UUID/雪花算法)并设置一个有效时间(避免死锁),注意value值必须是唯一的字符串(后期作为解锁条件之一的判断依据(自动失效也是一种))
在加锁的时候还需要设置一个加锁的超时时间,若超过这个时间则放弃获取锁
释放锁的时候通过UUID判断该线程的锁是不是该锁,若不是则放弃解锁,否则执行delete
核心代码
import redis.clients.jedis.Jedis;
import util.JedisUtil;
import java.util.UUID;
public class LockUtil {
public String LockTimeout(long lockTime, int lockExpire, String lockName) {
Jedis jedis = null;
try {
jedis = new JedisUtil().getInstance();
String value;
if (lockExpire <= 0 || lockTime <= 0) {
return null;
}
value = UUID.randomUUID().toString();
//参试获取锁
Long islock = jedis.setnx(LockConst.LOCK_NAME_PRIFIX + lockName, value);
if (islock > 0) {
//成功获取锁后,加有效时间防止死锁
jedis.expire(LockConst.LOCK_NAME_PRIFIX + lockName, lockExpire);
System.out.println("加锁成功");
return value;
} else {
//获取锁失败后,指定时间内重试
while (System.currentTimeMillis() < (lockTime + lockExpire)) {
// System.out.println("在尝试获取锁!!");
islock = jedis.setnx(LockConst.LOCK_NAME_PRIFIX + lockName, value.toString());
if (islock > 0) {
jedis.expire(LockConst.LOCK_NAME_PRIFIX + lockName, lockExpire);
System.out.println("在尝试,加锁成功");
return value;
}
}
return null;
}
} finally {
if (jedis != null) {
jedis.close();
}
}
}
public boolean unLock(String locakName, String value) {
Jedis jedis = new JedisUtil().getInstance();
if (value == null || locakName == null) {
return false;
}
try {
//value只根据解锁一致的则解锁
String val = jedis.get(LockConst.LOCK_NAME_PRIFIX + locakName);
if (value.equals(val)) {
jedis.del(LockConst.LOCK_NAME_PRIFIX + locakName);
System.out.println("unlock成功");
return true;
}
System.out.println("unlock失败,该锁不是该线程上的");
return false;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null)
jedis.close();
}
return false;
}
}