序文
すでにほとんどのコンテンツRedissonの書かれたように、我々は公式サイトRedisson成分の合計を見てみましょう。
image.png
セマフォとされたCountDownLatchを残りの二つは、私たちが進捗状況を構築し、迅速Redissonはそれを達成する方法について説明します、があります。
我々はすべて言っても過言でありません、JDKでたCountDownLatchセマフォと2人の兄弟を知って、戻って見ることができます理解していません。
使用のセマフォ例
次の図の下のセマフォの外観:
image.png
その後、我々はRedissonを使用する場合を見てみましょう。
RSemaphore semaphore = redisson.getSemaphore("semaphore");
// 同时最多允许3个线程获取锁
semaphore.trySetPermits(3);
for(int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]尝试获取Semaphore锁");
semaphore.acquire();
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]成功获取到了Semaphore锁,开始工作");
Thread.sleep(3000);
semaphore.release();
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]释放Semaphore锁");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
セマフォソースの解析
そして、上記の例によると、私たちは、ソースコードの実装方法を参照してください。
最初のステップ:
semaphore.trySetPermits(3)。
public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
@Override
public boolean trySetPermits(int permits) {
return get(trySetPermitsAsync(permits));
}
@Override
public RFuture<Boolean> trySetPermitsAsync(int permits) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"local value = redis.call('get', KEYS[1]); " +
"if (value == false or value == 0) then "
+ "redis.call('set', KEYS[1], ARGV[1]); "
+ "redis.call('publish', KEYS[2], ARGV[1]); "
+ "return 1;"
+ "end;"
+ "return 0;",
Arrays.<Object>asList(getName(), getChannelName()), permits);
}
}
実装プロセス:
- 現在の値を取得するために、セマフォ取得
- セマフォがロックを取得するために、クライアントは数3に設定されている許可することができつつ、第1のデータは、その後、3セマフォセット、0であります
- そして、リターンをいくつかのニュースを公開する1
そして、見とるsemaphore.acquire();
とsemaphore.release();
ロジックを:
public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
@Override
public RFuture<Boolean> tryAcquireAsync(int permits) {
if (permits < 0) {
throw new IllegalArgumentException("Permits amount can't be negative");
}
if (permits == 0) {
return RedissonPromise.newSucceededFuture(true);
}
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"local value = redis.call('get', KEYS[1]); " +
"if (value ~= false and tonumber(value) >= tonumber(ARGV[1])) then " +
"local val = redis.call('decrby', KEYS[1], ARGV[1]); " +
"return 1; " +
"end; " +
"return 0;",
Collections.<Object>singletonList(getName()), permits);
}
@Override
public RFuture<Void> releaseAsync(int permits) {
if (permits < 0) {
throw new IllegalArgumentException("Permits amount can't be negative");
}
if (permits == 0) {
return RedissonPromise.newSucceededFuture(null);
}
return commandExecutor.evalWriteAsync(getName(), StringCodec.INSTANCE, RedisCommands.EVAL_VOID,
"local value = redis.call('incrby', KEYS[1], ARGV[1]); " +
"redis.call('publish', KEYS[2], value); ",
Arrays.<Object>asList(getName(), getChannelName()), permits);
}
}
ロックされたロジックを見てみましょうtryAcquireAsync()
:
- 、の現在の値を取得するために、セマフォ取得3,3> 1言います
- 1セマフォdecrbyクライアントの数、ロックセマフォを獲得することを可能にする2 1だけデクリメントされます
- decrbyセマフォ1
- decrbyセマフォ1
- 3つのロックを行った後、セマフォ値が0であります
再び直接ロックされ、この時間が0を返す場合、その後、以下に示すように、ロックを取得する無限ループに入ります。
image.png
そして、ロック解除のロジックを見てみましょうreleaseAsync()
:
- incrbyは、クライアントがロックを解放するたびに、それは1の累積量の値に信号を1セマフォ、セマフォの値が0ではありません
理解するには、ここを参照してください、Redissonセマフォは実際には非常に簡単です達成
使用されたCountDownLatchの例
ユースケース:
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(3);
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]设置了必须有3个线程执行countDown,进入等待中。。。");
for(int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]在做一些操作,请耐心等待。。。。。。");
Thread.sleep(3000);
RCountDownLatch localLatch = redisson.getCountDownLatch("anyCountDownLatch");
localLatch.countDown();
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]执行countDown操作");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
latch.await();
System.out.println(new Date() + ":线程[" + Thread.currentThread().getName() + "]收到通知,有3个线程都执行了countDown操作,可以继续往下走");
たCountDownLatchソースの解析
ソースとして、次のとおりです。
public class RedissonCountDownLatch extends RedissonObject implements RCountDownLatch {
@Override
public RFuture<Boolean> trySetCountAsync(long count) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"if redis.call('exists', KEYS[1]) == 0 then "
+ "redis.call('set', KEYS[1], ARGV[2]); "
+ "redis.call('publish', KEYS[2], ARGV[1]); "
+ "return 1 "
+ "else "
+ "return 0 "
+ "end",
Arrays.<Object>asList(getName(), getChannelName()), newCountMessage, count);
}
@Override
public RFuture<Void> countDownAsync() {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"local v = redis.call('decr', KEYS[1]);" +
"if v <= 0 then redis.call('del', KEYS[1]) end;" +
"if v == 0 then redis.call('publish', KEYS[2], ARGV[1]) end;",
Arrays.<Object>asList(getName(), getChannelName()), zeroCountMessage);
}
}
第1の解析trySetCount()
方法のロジック:
- anyCountDownLatchが初めて、存在は確かに存在しません。
- セットredisson_countdownlatch__channel__anyCountDownLatch 3
- 戻る1
次の分析のlatch.await();
下に示されているような方法:
image.png
この方法は、実際にはそれ以外の場合は、死のサイクルから撤退し、常にそれから、値anyCountDownLatchを取得した値がゼロより大きい場合、死のサイクルを継続し、しばらく真のループに陥っています
最後にlocalLatch.countDown();
方法:
- DECR anyCountDownLatch、つまり、毎回クライアントを行うカウントダウン操作は、実際には、1 cocuntDownLatchの値を小さくします
await()
態様は、0がその独自のロジックを実行する場合anyCountDownLatchに対応する格納された値が、0であるかどうか、判断する無限ループを分析しました
概要
二つの成分は非常に単純ではありませんここを参照してください?
ここに、学習のRedisson部分が終わって、我々は分散ロックを実装ZKの原理を学びます。
宣言
:私のブログから始まるこの記事https://www.cnblogs.com/wang-mengと公共番号:ロマンチックみなさ一つramiflorous BEは、ソースを明記してください転載必要があります!
興味のパートナーは、個々の国民の少数心配することができる:一つの枝にはロマンチックな花を数えます