Redission-tryLock()源码解析

Redisson的加锁方法有两个,tryLock和lock,使用上的区别在于tryLock可以设置锁的过期时长leaseTime和等待时长waitTime,核心处理的逻辑都差不多

    public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        long time = unit.toMillis(waitTime);
        long current = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();

        // 尝试获取锁,如果没取到锁,则返回锁的剩余超时时间 
        Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
        // lock acquired

        // ttl为null,说明可以抢到锁了,返回true 
        if (ttl == null) {
            return true;
        }
        

        // 如果waitTime已经超时了,就返回false,代表申请锁失败 
        time -= System.currentTimeMillis() - current;
        if (time <= 0) {
            acquireFailed(waitTime, unit, threadId);
            return false;
        }
        
        current = System.currentTimeMillis();

        /**
        订阅锁释放事件,并通过 await 方法阻塞等待锁释放,有效的解决了无效的锁申请浪费资源的问题:
    基于信息量,当锁被其它资源占用时,当前线程通过 Redis 的 channel 订阅锁的释放事件
    一旦锁释放会发消息通知待等待的线程进行竞争.
        */
        RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
        if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
            if (!subscribeFuture.cancel(false)) {
                subscribeFuture.onComplete((res, e) -> {
                    if (e == null) {
                        unsubscribe(subscribeFuture, threadId);
                    }
                });
            }
            acquireFailed(waitTime, unit, threadId);
            return false;
        }

        try {

            //如果获取锁的耗时超过最大等待时间,加锁失败
            time -= System.currentTimeMillis() - current;
            if (time <= 0) {
                acquireFailed(waitTime, unit, threadId);
                return false;
            }

            //在最大等待时间内循环获取锁
            while (true) {
                long currentTime = System.currentTimeMillis();
                ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
                // lock acquired
                if (ttl == null) {
                    return true;
                }

                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) {
                    acquireFailed(waitTime, unit, threadId);
                    return false;
                }

                // waiting for message
                currentTime = System.currentTimeMillis();

                // waiting for message,等待解锁消息
                if (ttl >= 0 && ttl < time) {
                    subscribeFuture.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                } else {
                    subscribeFuture.getNow().getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
                }

                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) {
                    acquireFailed(waitTime, unit, threadId);
                    return false;
                }
            }
        } finally {
            //取消订阅消息
            unsubscribe(subscribeFuture, threadId);
        }
//        return get(tryLockAsync(waitTime, leaseTime, unit));
    }

Redission分布式锁原理_知知之之的博客-CSDN博客_redission实现分布式锁原理原理源码中加锁lua代码if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end;if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) thenhttps://blog.csdn.net/weixin_35973945/article/details/124151830

需要特别注意的是,RedissonLock 同样没有解决 节点挂掉的时候,存在丢失锁的风险的问题。而现实情况是有一些场景无法容忍的,所以 Redisson 提供了实现了redlock算法的 RedissonRedLock,RedissonRedLock 真正解决了单点失败的问题,代价是需要额外的为 RedissonRedLock 搭建Redis环境。

所以,如果业务场景可以容忍这种小概率的错误,则推荐使用 RedissonLock, 如果无法容忍,则推荐使用 RedissonRedLock。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redisson是一个Java驻留在内存数据网格(in-memory data grid)中的分布式Java锁和同步工具。 tryLock() 方法用于获取锁,如果锁可用并且获取成功,则返回 true。如果锁不可用,则此方法立即返回 false。 lock() 方法用于获取锁。如果锁可用,则获取锁并立即返回 true。如果锁不可用,则此方法将阻塞,直到获取到锁为止。 ### 回答2: Redisson是一个Java Redis客户端,为Java开发人员提供了极其丰富的Redis客户端功能和分布式数据结构的应用程序接口(API)。其中,Redisson的trylocklock方法是非常重要的,它们可以帮助我们实现缓存锁以及分布式锁。 首先,让我们来了解一下Redisson的lock方法。lock方法是一种阻塞锁,当锁已经被其他线程占用时,当前线程会一直等待,直到获得锁为止。该方法在Redis中实现了单个节点、集群和Redis Sentinel的支持。我们可以使用以下代码来实现锁: /** * 获取锁: * lock.lock(); //阻塞式获取锁,如果没有获取到就一直等待 * * 业务处理: * ... * * 释放锁: * lock.unlock(); //释放锁 **/ 在上述代码中,使用lock.lock()方法获取锁,此时如果锁被其他线程占用,则当前线程会一直等待,直到获得锁为止。在该锁被占用时,其他线程不能访问锁中的资源。 接下来,我们介绍Redisson的tryLock方法。和lock方法不同,tryLock方法是一种非阻塞锁,当锁被其他线程占用时,当前线程不会一直等待,而是立刻返回false。我们可以使用以下代码来实现tryLock: /** * 获取锁: * boolean result = lock.tryLock(); //非阻塞式获取锁,获取不到就返回false * if(result){ * 业务处理: * ... * * 释放锁: * lock.unlock(); //释放锁 * } * else{ * System.out.println("获取锁失败!"); * } **/ 在上述代码中,使用lock.tryLock()方法获取锁,此时如果锁被其他线程占用,则当前线程立刻返回false。在该锁被占用时,当前线程可以选择进行其他操作,而不是一直等待。这个方法特别适用于需要高效率的场景,因为它避免了线程之间的等待。 总结一下,Redisson的locktryLock方法都可以帮助我们实现缓存锁和分布式锁,这两种方法都有各自的优缺点。开发人员可以根据实际情况选择合适的锁方法,以达到更高的效率。同时,在使用锁的过程中,也需要避免死锁和抢锁失败的情况,以及对性能的影响。 ### 回答3: Redission是一个Java实现的分布式锁,其中包括两种不同的锁方式:trylocklocktrylock指的是尝试获取锁,若该锁没有被其他线程持有,则获取成功并返回true,否则不会等待持有者释放锁,而是立即返回false。使用trylock方式可以避免线程长时间等待,从而提高了效率。 lock是一种比较常见的获取锁的方式,它会进行阻塞直到获取到锁为止。一旦获取锁,则其他线程将无法访问共享资源,直到持有锁的线程释放掉锁。Lock方式可以保证每一次获取到锁都是安全的,在分布式系统中也能够保证数据的一致性。 对于这两种锁方式,在使用前需要先创建一个RedissonClient对象,初始化对应的分布式锁,然后再通过locktrylock方法来获取锁。 需要注意的是,在使用分布式锁时要避免死锁,因此需要在代码中合理使用锁的释放方式,以避免程序出现异常导致无法正常释放锁。 总之,Redissiontrylocklock都是实现分布式锁的方法,但使用方式略有不同。通过合理使用这两种锁方式,可以保证系统在分布式环境下的数据一致性和高并发性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值