redisson源码-加锁

1.原理图

2.获取锁的方法

//获取锁
void lock();
//获取锁,并设置锁过期时间
void lock(long leaseTime, TimeUnit unit);
//尝试获取锁,成功返回true
boolean tryLock();
//尝试获取锁,成功返回true,waitTime等待时间,leaseTime释放锁时间默认为-1
boolean tryLock(long time, TimeUnit unit) throws InterruptedException
//参照上
boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
//获取锁
public void lock(long leaseTime, TimeUnit unit) {
    try {
        lockInterruptibly(leaseTime, unit);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}
//lock相关方法实际执行的方法
public void lockInterruptibly(long leaseTime, TimeUnit unit)throws InterruptedException{
//当前线程id
long threadId = Thread.currentThread().getId();
//执行lua脚本获取锁,ttl返回的的是返回锁的过期时间(只有锁没获取成功才会返回过期时间)
Long ttl = tryAcquire(leaseTime, unit, threadId);
// lock acquired
if (ttl == null) {
    return;
}
//如果获取锁失败,则订阅到对应这个锁的channel,但其他线程释放锁时,通知线程去获取锁
RFuture<RedissonLockEntry> future = subscribe(threadId);
/
commandExecutor.syncSubscription(future);

try {
    //死循环尝试获取锁
    while (true) {
        ttl = tryAcquire(leaseTime, unit, threadId);
        // lock acquired
        if (ttl == null) {
            break;
        }

        // waiting for message
        if (ttl >= 0) {
            getEntry(threadId).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
        } else {
            getEntry(threadId).getLatch().acquire();
        }
    }
} finally {
    //取消订阅
    unsubscribe(future, threadId);
}
}

//获取锁方法,
private Long tryAcquire(long leaseTime, TimeUnit unit, long threadId) {
//get方法实际是线程池执行,返回锁失效时间    
return get(tryAcquireAsync(leaseTime, unit, threadId));
}
//
private <T> RFuture<Long> tryAcquireAsync(long leaseTime, TimeUnit unit, long threadId) {
    if (leaseTime != -1) {
        //执行lua脚本获取锁
        return tryLockInnerAsync(leaseTime, unit, threadId, RedisCommands.EVAL_LONG);
    }
    //getLockWatchdogTimeout 默认时间30s释放锁
    RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(), TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
    ttlRemainingFuture.onComplete((ttlRemaining, e) -> {
        if (e != null) {
            return;
        }

        // lock acquired
        if (ttlRemaining == null) {
            定时任务不断续锁(看门狗)
            scheduleExpirationRenewal(threadId);
        }
    });
    return ttlRemainingFuture;
}
//获取锁,可重入锁,返回锁过期时间
<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
    internalLockLeaseTime = unit.toMillis(leaseTime);

    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,
              //==0表示key不存在,无线程获取锁
              "if (redis.call('exists', KEYS[1]) == 0) then " +
                  如果不存在,则设置key的 某个字段 value=1
                  "redis.call('hset', KEYS[1], ARGV[2], 1); " +
                   设置key过期时间
                  "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                  "return nil; " +
              "end; " +
              //hexists等于1表示存在
              "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
                  //设置key的 某个字段加1
                  "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
                  "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                  "return nil; " +
              "end; " +
               //其他线程无法获取到锁,返回过期时间
              "return redis.call('pttl', KEYS[1]);",
                Collections.<Object>singletonList(getName()), internalLockLeaseTime, getLockName(threadId));

//getName()我们定义锁的key,internalLockLeaseTime释放时间,
//getLockName(threadId)为id + ":" + threadId,id为uuId
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值