加解锁思路
加锁

解锁

代码实现
private static final Long SUCCESS = 1L;
/**
* 加锁逻辑
*
* @param lock 要加的锁
* @param requestId 客户端标识(谁加的锁,谁才有权限去解这个锁)
* @param expireTime 过期时间(锁的持有者没解锁就挂了,到期自动解锁,避免死锁)
* @return 是否加锁成功
*/
public boolean getLock(String lock, String requestId, int expireTime) {
Jedis jedis = new Jedis();
// 1. 锁未被占用(key不存在),那么就加锁,并对锁设置过期时间
// 2. 锁被占用(key存在),不做任何操作
String result = jedis.set(lock, requestId, "NX", "PX", expireTime);
return "OK".equals(result);
}
/**
* 解锁逻辑
*
* @param lock 要解的锁
* @param requestId 客户端标识
* @return 是否解锁成功
*/
public boolean unlock(String lock, String requestId) {
Jedis jedis = new Jedis();
// Lua脚本(里面的所有操作具有原子性)
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
// lock --> KEYS[1] , requestId --> ARGV[1]
// 1、获取lock的值value;2、value与requestId对比;3、若相等则删除lock,否则return 0
Object result = jedis.eval(script, Arrays.asList(lock), Arrays.asList(requestId));
return SUCCESS.equals(result);
}
测试代码
// 锁
private static final String LOCK = "sss";
// 客户端A标识(方便测试,这里简单随便写个值)
private static String clientA = "clientA";
// 客户端B标识
private static String clientB = "clientB";
// 过期时间
private static int expireTime = 30000;
@Test
public void getLockByClientA() {
printResult(clientA, getLock(LOCK, clientA, expireTime), 1);
}
@Test
public void unlockByClientA() {
printResult(clientA, unlock(LOCK, clientA), 2);
}
@Test
public void getLockByClientB() {
printResult(clientB, getLock(LOCK, clientB, expireTime), 1);
}
@Test
public void unlockByClientB() {
printResult(clientB, unlock(LOCK, clientB), 2);
}
public void printResult(String client, boolean result, int mode) {
String op = (mode == 1 ? "获取锁" : "释放锁");
String status = (result ? "成功" : "失败");
System.out.println(client + op + status);
}
@Test
public void checkLock() {
Jedis jedis = new Jedis();
String requestId = jedis.get(LOCK);
Long time = jedis.pttl(LOCK);
if (time.equals(-2L)) {
System.out.println("锁" + LOCK + "未被占用,可获取");
} else if (time.equals(-1L)) {
System.out.println("锁" + LOCK + "已被" + requestId + "占用,没有设置过期时间");
} else {
System.out.println("锁" + LOCK + "已被" + requestId + "占用," + time + "毫秒后将过期");
}
}
@Test
public void testDemo() {
checkLock();
getLockByClientA();
checkLock();
getLockByClientB();
unlockByClientB();
checkLock();
unlockByClientA();
checkLock();
getLockByClientB();
}
测试结果
