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