Redisson之lock()和tryLock()的区别

这篇具有很好参考价值的文章主要介绍了Redisson之lock()和tryLock()的区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Redisson之lock()和tryLock()的区别和原理解析

在Redisson中 lock() 方法 与 tryLock() 方法是有区别的!

我们先来阐述两者的区别,再分析它们的源码。

lock() 与 tryLock() 的区别

(1)返回值: lock() 是没有返回值的;tryLock() 的返回值是 boolean。

(2)时机:lock() 一直等锁释放;tryLock() 获取到锁返回true,获取不到锁并直接返回false

(3)tryLock() 是可以被打断的,被中断的;lock是不可以。

tryLock()

@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
    // 转成毫秒,后面都是以毫秒为单位
    long time = unit.toMillis(waitTime);
    // 当前时间
    long current = System.currentTimeMillis();
    // 线程ID-线程标识
    long threadId = Thread.currentThread().getId();
 
    // 尝试获取锁 tryAcquire() !!!
    Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId);
        
    // 如果上面尝试获取锁返回的是null,表示成功;如果返回的是时间则表示失败。
    if (ttl == null) {
        return true;
    }
 
    // 剩余等待时间 = 最大等待时间 -(用现在时间 - 获取锁前的时间)
    time -= System.currentTimeMillis() - current;
 
    // 剩余等待时间 < 0 失败
    if (time <= 0) {
        acquireFailed(waitTime, unit, threadId);
        return false;
    }
 
    // 再次获取当前时间
    current = System.currentTimeMillis();
    // 重试逻辑,但不是简单的直接重试!
    // subscribe是订阅的意思
    RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
    // 如果在剩余等待时间内,收到了释放锁那边发过来的publish,则才会再次尝试获取锁
    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);
 
            // 成功
            if (ttl == null) {
                return true;
            }
            
            // 又获取锁失败,再次计算上面的耗时
            time -= System.currentTimeMillis() - currentTime;
            if (time <= 0) {
                acquireFailed(waitTime, unit, threadId);
                return false;
            }
 
            currentTime = System.currentTimeMillis();
            // 采用信号量的方式重试!
            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);
    }
}

lock()

private void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws InterruptedException {

	// 获取当前线程 ID
    long threadId = Thread.currentThread().getId();
    // 获取锁,正常获取锁则ttl为null,竞争锁时返回锁的过期时间
    Long ttl = tryAcquire(-1, leaseTime, unit, threadId);
    if (ttl == null) {
        return;
    }
		
    // 订阅锁释放事件
    // 如果当前线程通过 Redis 的 channel 订阅锁的释放事件获取得知已经被释放,则会发消息通知待等待的线程进行竞争
    RFuture<RedissonLockEntry> future = subscribe(threadId);
    if (interruptibly) {
        commandExecutor.syncSubscriptionInterrupted(future);
    } else {
        commandExecutor.syncSubscription(future);
    }

    try {
        while (true) {
            // 循环重试获取锁,直至重新获取锁成功才跳出循环
            // 此种做法阻塞进程,一直处于等待锁手动释放或者超时才继续线程    
            ttl = tryAcquire(-1, leaseTime, unit, threadId);
            if (ttl == null) {
                break;
            }

            if (ttl >= 0) {
                try {
                    future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    if (interruptibly) {
                        throw e;
                    }
                    future.getNow().getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                }
            } else {
                if (interruptibly) {
                    future.getNow().getLatch().acquire();
                } else {
                    future.getNow().getLatch().acquireUninterruptibly();
                }
            }
        }
    } finally {
        // 最后释放订阅事件
        unsubscribe(future, threadId);
    }
}

建议应尽量使用tryLock(),且携带参数,因为可设置最大等待时间以及可及时获取加锁返回值,后续可做一些其他加锁失败的业务文章来源地址https://www.toymoban.com/news/detail-443119.html

到了这里,关于Redisson之lock()和tryLock()的区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java——》Synchronized和Lock区别

    推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结——》【SpringBoot】     总结——》【MyBatis、MyBatis-Plus】     总结——》【Linux】     总结——》【MongoDB】    

    2024年02月09日
    浏览(41)
  • Redis之Redisson原理详解

    Redisson 顾名思义, Redis 的儿子,本质上还是 Redis 加锁,不过是对 Redis 做了很多封装,它不仅提供了一系列的分布式的 Java 常用对象,还提供了许多分布式服务。 Redisson 和 Jedis 、 Lettuce 有什么区别? Redisson 和它俩的区别就像一个用鼠标操作图形化界面,一个用命令行操作文

    2024年02月09日
    浏览(41)
  • Synchronized与Lock的区别和优缺点

    1.   synchronized 是 Java 的一个内置特性,而 Lock 是 Java 的一个接口类; 2.   synchronized 在发生异常时会自动释放线程占用的锁,而 Lock 在发生异常时(不发生也一样)需要主动在 finally 中调用 unLock() 去释放锁; 3.   Lock 可以让等待锁的线程响应中断,而 synchronized 无法

    2024年02月08日
    浏览(45)
  • Redisson分布式锁 原理&源码 分析

    获取锁的Lua脚本: 释放锁的Lua脚本: tryLock()底层代码分析 time :剩余的等待重试时间 ttl :现被持有的锁的剩余有效时间 计算尝试获取锁所消耗的时间,然后再计算出等待获取锁的剩余时间time, 如果time=0,则不再重试了直接返回获取锁失败, 如果time0,则通过subscribe去

    2024年02月11日
    浏览(64)
  • Redisson 分布式锁可重入的原理

    目录 1. 使用 Redis 实现分布式锁存在的问题 2. Redisson 的分布式锁解决不可重入问题的原理 不可重入:同一个线程无法两次 / 多次获取锁 举例 method1 执行需要获取锁 method2 执行也需要(同一把)锁 如果 method1 中调用了 method2,就会出现死锁的情况 method1 执行的过程是同一个线

    2024年01月25日
    浏览(43)
  • Redis分布式锁及Redisson的实现原理

    Redis分布式锁 在讨论分布式锁之前我们回顾一下一些单机锁,比如synchronized、Lock 等 锁的基本特性: 1.互斥性:同一时刻只能有一个节点访问共享资源,比如一个代码块,或者同一个订单同一时刻只能有一个线程去支付等。 2.可重入性: 允许一个已经获得锁的线程,在没有释

    2024年02月06日
    浏览(43)
  • package.json 与 package-lock.json文件的区别

    一、什么是package.json文件 package.json记录当前项目中下载了哪些包(npm install xxx 包信息),记录你下载的包信息(地址、版本号等),不包含依赖包信息。 package.json文件记录你项目中所需要的所有模块。当你执行npm install的时候,node会先从package.json文件中读取所有dependencies信

    2024年02月06日
    浏览(45)
  • Redisson 分布式限流器 RRateLimiter 的使用及原理

    trySetRate 用于设置限流参数。其中 RateType 包含 OVERALL 和 PER_CLIENT 两个枚举常量,分别表示全局限流和单机限流。后面三个参数表明了令牌的生成速率,即每 rateInterval 生成 rate 个令牌, rateIntervalUnit 为 rateInterval 的时间单位。 acquire 和 tryAcquire 均可用于获取指定数量的令牌,不

    2024年01月20日
    浏览(50)
  • 从原理到实践,分析 Redisson 分布式锁的实现方案(二)

            上篇讲解了如何用 Redis 实现分布式锁的方案,它提供了简单的原语来实现基于Redis的分布式锁。然而,Redis作为分布式锁的实现方式也存在一些缺点。本文将引入Redisson来实现分布式锁。         Redisson是一个基于Redis的分布式Java框架。它提供了丰富的功能和工

    2024年02月15日
    浏览(46)
  • 深度解析Redisson框架的分布式锁运行原理与高级知识点

    分布式系统中的锁管理一直是一个复杂而关键的问 题。在这个领域,Redisson框架凭借其出色的性能和功能成为了开发者的首选之一。本篇博客将深入探讨Redisson框架的分布式锁运行原理以及涉及的高级知识点。通过详细的解释和示例代码,您将更好地理解如何在分布式环境中

    2024年02月09日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包