まず、スレッド間の同時実行
我々は2つのスレッドが同期実行したい場合は、あなただけのsychronziedを追加したり、同じJVM同期プロセス内で複数のスレッドの実施を確保するためにReetrantlockクラスを使用する必要があります。
したがって、このシステムは、例えば、分散されている場合:両方のサーバーのスレッドが同時にそれを行う方法にしたいを実行しますか?
そして、我々は達成したいこのサブサブドロップということです。
実際には、最も重要なのは、入手してロックを解除し、ロックの操作のためです。
二、達成のRedis
1、ロック
set(key,线程的id,30,NX)
ロックはRedisのにデータを置くことによって達成され、この設定方法:現在ではありません、このキーをRedisの、0が返された場合は1を返します。することができますこの方法です。異なるスレッド間の制御の同時実行、取得ロック考えこの方法復帰1の唯一の実装に設定方法。
後者の2つのパラメータが有効期限を設定しています。あなたが設定されていない場合はどうなりますか?たとえば、スレッドAがロックを取得し、その後、プログラムが死亡した失敗し、ロックがサーバーがロックを取得することはできません、他のスレッドが発売されていないされています。:だから、意義の有効期限を設定したロックのセットを得ることができ、他のスレッドには影響を与えないロックの解除で、(もちろん、あなたはメモリがRedisの良い除去メカニズムを設定したい)有効期限に達した後、データは自動的にキャンセルされます。
いくつかは)それは:(それは次の擬似コードです達成することができると言います
setnx(key,1)
expire(key,30)
Redisのは、達成するためにこれらの2つのコマンドを使用します。答えはNOです
私たちは、プロセスがロックされていることを確認する必要がありアトミック操作を、例えば、(キー、1)の後にsetnxを実行した後、クライアントのスレッドAの終わりを死んでいる、ロックが別のスレッドによって獲得されていません。
2、ロックが解除されます
スレッドが同期コードブロックの完了後に実行される、実行ロックが解除されます
del(key)
この方法では、それは大丈夫でしょうか?NO、NO、NO。絶対にありません
考えてみましょうこの:有効期限は、現在、30秒に設定されている場合、実行スレッドAの後に、コンテンツの同期コードブロックでロックを取得、30秒後に、Redisのは削除キーを入れ、時間を見て、ロックが解除され、それが完成し、まだ、そのスレッドBSETビットを実行して、あなたがロックを得ることができることを発見し、楽しい遊びで、スレッドBが、今回はそれがオーバー実行スレッドませんでした。この時間は、(それがロックを解除するに気付かないのRedisロックスレッドBも削除されている)、この男は、彼はまだそれを解放し、それをロックしていたと思った、この時間は、キーは、この男は、ロックが削除されたか分からないんです。このように、同時実行の問題があります。cuckoldedされているように私は同じことを知りません。
我々は(:+ IDは一意にサーバ・スレッド=値を識別する個人の思考である)スレッドIDに格納された値のセットを設定することができ
加锁:
String threadId = Thread.currentThread().getId()
set(key,threadId ,30,NX)
解锁:
if(threadId .equals(redisClient.get(key))){
del(key)
}
しかし、それは問題が登場し、ロック解除は、アトミック操作ではありません。私はああの問題になりますがに依存しています。
このようなシナリオで見てみましょう:
または、前の例の場合は、裁判官の後に完成したスレッドAが現在のスレッドIDではありません、そしてキー瞬間が満了しました。Bスレッドはロックされ、その後、Aがまだ上記の場合に現れ行いました。
我々は、使用のluaスクリプトを達成するために、バックル1をデルに置き換える必要があります。
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1]
then return redis.call('del', KEYS[1]) else return 0 end";
redisClient.eval(luaScript , Collections.singletonList(key), Collections.singletonList(threadId));
小さなパートナーはAがまだ実行して、最初の有効期限が切れるスレッドそして、言わなければならない、スレッドBはああ規則に準拠していないロックを獲得するために実行されています。ここでは、この問題を解決する必要があります。
私たちは、JRのガードレブロン・ジェームズ(数年前のもの)のように、糸ナイフガードを設定することができます。インペリアルガードに、Javaで、スレッドの守護者です!もちろん、あなたがスレッドの守護者であるかを知る必要があります。
このデーモンスレッドが唯一の役割です、
29秒が経過すると、スレッドAが行われていない、この時間デーモンスレッドが20秒間ロック「継続的な生活」のための説明書を期限切れに実行されます。デーモンスレッドは、20秒ごとに一度実行するために29秒から実行を開始します。
スレッドAが実行されると、このデーモンスレッドがオーバーになります。