持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
CountDownLatch
也是Redis
分布式锁支持的一种,同步组件。
CountDownLatch
倒们栓:必须有满足数量的线程来获取锁,达到线程的数量之后,才会往下走; 否则,阻塞。
举个栗子:倒们栓设置 3个。
@Test
public void test8() throws InterruptedException {
RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch");
countDownLatch.trySetCount(3);
System.out.println(LocalDateTime.now()
+ " : 线程[" + Thread.currentThread().getName()
+ "] 设置了必须有3个线程执行 countDown,进入等待中。。。");
for (int i = 0; i < 3; ++i) {
new Thread(() -> {
try {
System.out.println(LocalDateTime.now()
+ " : 线程[" + Thread.currentThread().getName()
+ "] 在做一些操作,请耐心等待。。。");
Thread.sleep(3000);
RCountDownLatch localLatch =
redisson.getCountDownLatch("countDownLatch");
localLatch.countDown();
System.out.println(LocalDateTime.now()
+ " : 线程[" + Thread.currentThread().getName()
+ "] 执行 countDown 操作");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
countDownLatch.await();
System.out.println(LocalDateTime.now()
+ " : 线程[" + Thread.currentThread().getName()
+ "] 收到通知,有3个线程都执行了 countDown 操作,可以继续往下走");
}
输出结果:
2022-06-21T17:36:56.156 : 线程[main] 设置了必须有3个线程执行 countDown,进入等待中。。。
2022-06-21T17:36:56.158 : 线程[Thread-3] 在做一些操作,请耐心等待。。。
2022-06-21T17:36:56.158 : 线程[Thread-4] 在做一些操作,请耐心等待。。。
2022-06-21T17:36:56.158 : 线程[Thread-5] 在做一些操作,请耐心等待。。。
2022-06-21T17:36:59.203 : 线程[Thread-4] 执行 countDown 操作
2022-06-21T17:36:59.216 : 线程[Thread-5] 执行 countDown 操作
2022-06-21T17:36:59.216 : 线程[Thread-3] 执行 countDown 操作
2022-06-21T17:36:59.270 : 线程[main] 收到通知,有3个线程都执行了 countDown 操作,可以继续往下走
- 设置倒们栓数值源码定位:
RedissonCountDownLatch#trySetCountAsync
对应参数如下:
KEYS[1]
:锁的名称 "countDownLatch
"KEYS[2]
:通道名称,redisson_countdownlatch__channel__{锁名}
ARGV[1]
:CountDownLatchPubSub.NEW_COUNT_MESSAGE
ARGV[2]
:倒们栓数量,需要输入的
if redis.call('exists', KEYS[1]) == 0 then -- 不存在对应的 锁 key
redis.call('set', KEYS[1], ARGV[2]);
redis.call('publish', KEYS[2], ARGV[1]);
return 1 -- 返回成功
else
return 0 -- 返回失败
end
- 等待,源码定位:
RedissonCountDownLatch#await
public void await() throws InterruptedException {
RFuture<RedissonCountDownLatchEntry> future = subscribe();
try {
commandExecutor.syncSubscription(future);
// 无限循环
while (getCount() > 0) { // 当前倒们栓的数量 > 0
// waiting for open state
RedissonCountDownLatchEntry entry = getEntry();
if (entry != null) {
entry.getLatch().await(); // 等待某一段时间
}
}
} finally {
unsubscribe(future);
}
}
- 减少倒们栓数值,源码定位:
RedissonCountDownLatch#countDownAsync
对应参数如下:
KEYS[1]
:锁的名称 "countDownLatch
"KEYS[2]
:通道名称,redisson_countdownlatch__channel__{锁名}
ARGV[1]
:CountDownLatchPubSub.NEW_COUNT_MESSAGE
local v = redis.call('decr', KEYS[1]); -- 自减 -1
if v <= 0 then redis.call('del', KEYS[1]) end; -- 倒们栓数量 <=0,删除对应 key
if v == 0 then redis.call('publish', KEYS[2], ARGV[1]) end;