package com.aswatson.cdc.test;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config; import java.time.LocalDateTime;
import java.util.concurrent.*; /**
* boolean success = lock.tryLock(0, 0, TimeUnit.SECONDS); // 表示尝试获取锁,等待0秒,持有锁0秒钟
* 注意问题,存在的隐患: 虽然 tryLock(0, 0, TimeUnit.SECONDS)
*
* 首先1. 但实际锁的释放仍然会受到 Redisson 看门狗机制的影响。如果持有锁的线程未能在续约周期内续约锁的持有时间,那么锁可能会在超时后被自动释放。
* (默认是每隔 30 秒进行一次续约)来维持锁的有效性,避免因为持有锁的线程未能释放而造成锁的永久占用。或者自己unLock。
*
* 其次2. 确保你使用的 Redisson 版本与 Redis 版本兼容,并且不会因为版本问题导致锁的行为异常。目前测试用的是redis(2.7.17)、redisson(3.24.3)
*
* 其次3. 默认情况下,Redisson 的看门狗会定期发送续约请求给 Redis 服务器,以延长当前持有的锁的有效期。但是也有不会续约的可能性:
* Redis 连接中断、Redisson 配置问题、持有锁的线程崩溃、锁的最大持有时间到期。
*
* 其次4. 即使在业务逻辑中调用了阻塞操作(如 sleep),Redisson 也会在后台继续进行续约操作,以防止锁被意外释放。
*
*/
public class TestRedissonLeaveTimeLock { public static void main(String[] args) throws Exception { Config config = new Config();
config.useSingleServer().setAddress("redis://10.95.35.93:37495");
RedissonClient redissonClient = Redisson.create(config);
RLock lock = redissonClient.getLock("lockName");
System.out.println("创建好了RedissonClient" + getName()); int numThreads = 10;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch doneLatch = new CountDownLatch(numThreads); // 尽管 for 循环看起来是按顺序逐个,但实际上每个任务会并发地在后台执行。
// 这是因为每次调用 submit时,任务被提交给线程池,而线程池会根据可用的线程资源并发执行这些任务。
for (int i = 0; i < numThreads; i++) {
executor.submit(() -> {
try {
startLatch.await(); // 等待主线程的启动信号 System.out.println("获取锁前的时间:"+ getName());
boolean success = lock.tryLock(0, 0, TimeUnit.SECONDS); // 尝试获取锁,等待0秒,持有锁0秒钟
System.out.println("获取锁后的时间:"+ getName());
if (success) {
System.out.println("拿到锁"+ getName());
// 模拟业务处理耗时 大于锁过期,可能导致非自己持有的锁被释放。
TimeUnit.SECONDS.sleep(20);
} else {
System.out.println("未能获取到锁,已放弃尝试" + getName());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
doneLatch.countDown();// 每次减去1 // 判断当前线程是否持有锁
if (lock.isHeldByCurrentThread()) {
System.out.println("释放锁"+ getName());
lock.unlock();
}
}
});
} System.out.println("主线程即将释放所有等待的线程...");
startLatch.countDown(); // 释放定义的1条线程,开始并发执行
doneLatch.await(); // 等待所有线程10条完成
executor.shutdown();
System.out.println("所有线程执行完成" + getName());
} public static String getName() {
return Thread.currentThread().getName() + "---" + LocalDateTime.now();
} }

记一个,生产遇到的redission锁,释放问题:lock.tryLock(0, 0, TimeUnit.SECONDS)的更多相关文章

  1. 深入浅出 Java Concurrency (9): 锁机制 part 4 锁释放与条件变量 (Lock.unlock And Condition)

    本小节介绍锁释放Lock.unlock(). Release/TryRelease unlock操作实际上就调用了AQS的release操作,释放持有的锁. public final boolean ...

  2. MySql一个生产死锁案例分析

    接到上级一个生产环境MySQL死锁日志信息文件,需要找出原因并解决问题.我将死锁日志部分贴出如下: 在mysql中使用命令:SHOW ENGINE INNODB STATUS;总能获取到最近一些问题信 ...

  3. 如何创建一个简单的C++同步锁框架(译)

    翻译自codeproject上面的一篇文章,题目是:如何创建一个简单的c++同步锁框架 目录 介绍 背景 临界区 & 互斥 & 信号 临界区 互斥 信号 更多信息 建立锁框架的目的 B ...

  4. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

  5. 一个Redis实现的分布式锁

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.conne ...

  6. 从一个实例谈谈postgresql索引锁

    最近客户在使用我司开发的数据库时,报告了如下问题(也不能算是问题,就是疑惑吧),环境如下: OS : Red Hat Enterprise Linux Server release 6.7 (Sant ...

  7. 对象的notify方法的含义和对象锁释放的三种情况

    1,notify的含义     (1)notify一次只随机通知一个线程进行唤醒 (2)在执行了notify方法之后,当前线程不会马上释放该对象锁,呈wait状态的线程也不能马上获得该对象锁, 要等到 ...

  8. 事务(进程 ID 64)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。

    访问频率比较高的app接口,在后台写的异常日志会偶尔出现以下错误. 事务(进程 ID 64)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品.请重新运行该事务 实所有的死锁最深层的原因就是一个 ...

  9. 聊聊高并发(三十二)实现一个基于链表的无锁Set集合

    Set表示一种没有反复元素的集合类,在JDK里面有HashSet的实现,底层是基于HashMap来实现的.这里实现一个简化版本号的Set,有下面约束: 1. 基于链表实现.链表节点依照对象的hashC ...

  10. C# 最基本的涉及模式(单例模式) C#种死锁:事务(进程 ID 112)与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。请重新运行该事务,解决方案: C#关闭应用程序时如何关闭子线程 C#中 ThreadStart和ParameterizedThreadStart区别

    C# 最基本的涉及模式(单例模式) //密封,保证不能继承 public sealed class Xiaohouye    { //私有的构造函数,保证外部不能实例化        private  ...

随机推荐

  1. .NET静态代码织入——肉夹馍(Rougamo)发布3.0

    肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...

  2. JSON字符串数据转换指定实体对象数据

    一.引入需要的maven依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId> ...

  3. log4j的配置详解

    参考文章:https://www.jianshu.com/p/ccafda45bcea 引入log4j: 在项目中单独使用log4j进行日志的输出: maven依赖: <dependency&g ...

  4. vulnhub --> Web Machine: (N7)

    靶场下载地址 Web Machine: (N7) << 点我 开始打靶 ip发现: nmap扫描网段发现靶机ip:192.168.56.101 端口发现: 对靶机进行常规端口扫描 访问网站 ...

  5. docker --link容器互联

    目录 一.系统环境 二.docker容器互联概述 2.1 docker容器互联的三种方式 2.2 docker --link使用注意事项 2.3 docker --link原理 三.docker容器互 ...

  6. vue2遇到的一些错误

    一.VUE中的VUEX如何调用modules里面的mutations和state   ...mapMutations("workflow",['setApproverConfig' ...

  7. Android 12(S) MultiMedia Learning(八)NuPlayer Renderer

    NuPlayer的AVSync由Renderer实现,接下来主要来看AVSync的工作原理 相关代码位置: NuPlayerRenderer.cpp - OpenGrok cross referenc ...

  8. MD5计算,一个扩展类,哪里都能用

    最近有同学问到如何计算一个字节数组的MD5值,现在分享一个扩展类,有了它,MD5计算再也不用其他了. 先看示例: string s = "hello world"; var s_m ...

  9. 基于docker的cicd

    基于docker的cicd 飞书链接: https://dlk2qiw7lh.feishu.cn/docs/doccnyu14HTaamVzASIXreCSNjf 相关软件 链接:https://pa ...

  10. 8.11考试总结(NOIP模拟36)[Dove 打扑克·Cicada 与排序·Cicada 拿衣服]

    我会化作人间的风雨陪在你的身边 T1 Dove 打扑克 解题思路 考场上是想了一个树状数组维护的打法,但是竟然和 \(qn^2\) 的算法一样是 65pts 暴力就是对于每一次 2 询问重新建一下树状 ...