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(); } }
复制