经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
Redisson分布式闭锁RCountDownLatch的使用详细讲解
来源:jb51  时间:2023/2/13 8:43:55  对本文有异议

本篇文章基于redisson-3.17.6版本源码进行分析

一、RCountDownLatch的使用

RCountDownLatch的功能跟CountDownLatch,用于实现某个线程需要等待其他线程都完成之后,我再去执行,这种场景就可以使用CountDownLatch。

  1. @Test
  2. public void testRCountDownLatch() {
  3. Config config = new Config();
  4. config.useSingleServer().setAddress("redis://127.0.0.1:6379");
  5. RedissonClient redissonClient = Redisson.create(config);
  6. RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch("anyCountDownLatch");
  7. rCountDownLatch.trySetCount(5);
  8. for (int i = 1; i <= 5; i++) {
  9. new Thread(() -> {
  10. System.out.println(Thread.currentThread().getName() + "离开教师...");
  11. rCountDownLatch.countDown();
  12. }, "A" + i).start();
  13. }
  14. try {
  15. rCountDownLatch.await();
  16. } catch (InterruptedException e) {
  17. throw new RuntimeException(e);
  18. }
  19. System.out.println("班长锁门...");
  20. }

A1离开教师...
A2离开教师...
A4离开教师...
A3离开教师...
A5离开教师...
班长锁门...

二、trySetCount()设置计数器

  1. /**
  2. * 仅当先前的计数已达到零或根本未设置时才设置新的计数值。
  3. */
  4. boolean trySetCount(long count);
  1. public RFuture<Boolean> trySetCountAsync(long count) {
  2. return commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
  3. // 往redis中写入一个String类型的数据 anyCountDownLatch:5
  4. "if redis.call('exists', KEYS[1]) == 0 then "
  5. + "redis.call('set', KEYS[1], ARGV[2]); "
  6. + "redis.call('publish', KEYS[2], ARGV[1]); "
  7. + "return 1 "
  8. + "else "
  9. + "return 0 "
  10. + "end",
  11. Arrays.asList(getRawName(), getChannelName()), CountDownLatchPubSub.NEW_COUNT_MESSAGE, count);
  12. }

同样,在redis中写入了一个{key}:{计数器总数}的String类型的数据。

三、countDown()源码

减少锁存器的计数器。当计数达到零时通知所有等待线程。

  1. public RFuture<Void> countDownAsync() {
  2. return commandExecutor.evalWriteNoRetryAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
  3. // 减少redis中计数器的值
  4. "local v = redis.call('decr', KEYS[1]);" +
  5. // 计数器减为0后,删除对应的key
  6. "if v <= 0 then redis.call('del', KEYS[1]) end;" +
  7. "if v == 0 then redis.call('publish', KEYS[2], ARGV[1]) end;",
  8. Arrays.<Object>asList(getRawName(), getChannelName()), CountDownLatchPubSub.ZERO_COUNT_MESSAGE);
  9. }

四、await()源码

等到计数器达到零。

  1. public void await() throws InterruptedException {
  2. // 如果计数器为0,直接返回
  3. if (getCount() == 0) {
  4. return;
  5. }
  6. // 订阅redisson_countdownlatch__channel__{anyCountDownLatch}的消息
  7. CompletableFuture<RedissonCountDownLatchEntry> future = subscribe();
  8. RedissonCountDownLatchEntry entry = commandExecutor.getInterrupted(future);
  9. try {
  10. // 不断循环判断计数器的值是否大于0,大于0说明还有线程没执行完成,在这里阻塞:LockSupport.park(this)
  11. while (getCount() > 0) {
  12. // waiting for open state
  13. entry.getLatch().await();
  14. }
  15. } finally {
  16. unsubscribe(entry);
  17. }
  18. }

到此这篇关于Redisson分布式闭锁RCountDownLatch的使用详细讲解的文章就介绍到这了,更多相关Redisson RCountDownLatch内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号