当前位置: 首页 > 工具软件 > unlock > 使用案例 >

Redis源码分析之unlock

和选
2023-12-01
@Override
    public void unlock() {
        //解锁成功返回true
        Boolean opStatus = get(unlockInnerAsync(Thread.currentThread().getId()));
        if (opStatus == null) {
            throw new IllegalMonitorStateException("attempt to unlock lock, not locked by current thread by node id: "
                    + id + " thread-id: " + Thread.currentThread().getId());
        }
        if (opStatus) {
            //取消定时任务
            cancelExpirationRenewal();
        }
    }

第一步:发布解锁消息删除key

protected RFuture<Boolean> unlockInnerAsync(long threadId) {
    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
            "if (redis.call('exists', KEYS[1]) == 0) then " +
                "redis.call('publish', KEYS[2], ARGV[1]); " +
                "return 1; " +
            "end;" +
            "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +
                "return nil;" +
            "end; " +
            "local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +
            "if (counter > 0) then " +
                "redis.call('pexpire', KEYS[1], ARGV[2]); " +
                "return 0; " +
            "else " +
                "redis.call('del', KEYS[1]); " +
                "redis.call('publish', KEYS[2], ARGV[1]); " +
                "return 1; "+
            "end; " +
            "return nil;",
            Arrays.<Object>asList(getName(), getChannelName()), LockPubSub.unlockMessage, internalLockLeaseTime, getLockName(threadId));

}

调用lua脚本,exists命令:若 key 存在返回 1 ,否则返回 0 。 

publish 发布unlockMessage消息

hexists 如果哈希表含有给定字段,返回 1 。 如果哈希表不含有给定字段,或 key 不存在,返回 0 。

hincrby Redis Hincrby 命令用于为哈希表中的字段值加上指定增量值,此处是-1即减1,因为存在重入锁问题,N次上锁需要N次解锁

del 删除key

第二步:取消定时任务

void cancelExpirationRenewal() {
    //移除过期时间重置Map中的数据 并返回对应value
    Timeout task = expirationRenewalMap.remove(getEntryName());
    if (task != null) {
        //取消任务
        task.cancel();
    }
}
private static final ConcurrentMap<String, Timeout> expirationRenewalMap = PlatformDependent.newConcurrentHashMap();

调用lock(),tryLock()无参方法会生成一个定时任务,手动unlock的时候会取消任务

 

 类似资料: