Rentrant Lockを完全に理解するように教えてください。


1.Reentrant Lockの紹介
RentrantrantLockは、ロックインターフェースを実現するクラスであり、実際のプログラミングにおいて使用頻度が高いロックであり、重入性をサポートしており、共有リソースに対してロックを繰り返すことができること、すなわち、現在のスレッドがこのロックを取得しても再びブロックされないことを示しています。javaキーワードのsynchronized暗黙的なサポートの再入力性(synchronizedについてはこの記事が読めます)では、synchronizedは自己増加を取得することにより、自己減少を解放し再入力を実現します。一方、Reentrant Lockは、公平ロックと非公平ロックの両方をサポートしています。
では、完全にRentrantrantLockを理解するには、主にRentrant Lock同期語義の学習である。2.公平錠と非公平錠。
2.重入性の実現原理
再入力性をサポートするには、二つの問題を解決する必要があります。
1.オンラインでロックを取得した場合、ロックを取得したスレッドが現在のスレッドであれば、直接に再度取得することができます。
2.ロックはn回取得されるので、同じn回解除された後だけロックが完全解除されます。
この文章を通して、同期コンポーネントは主にAQSのいくつかのプロテックス法を書き直すことによって自分の同期語義を表現することを知っています。
最初の問題に対して、RentrantrantLockがどのように実現されているかを見てみます。非公平ロックを例にとって、現在のスレッドがロックされているかを判断します。コア方法はnonfairTryAcquireです。

final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//1.             ,          
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//2.    ,             
else if (current == getExclusiveOwnerThread()) {
// 3.     ,    
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

このコードのロジックも簡単です。具体的にはコメントを見てください。
重入性をサポートするために、第二のステップで処理ロジックを追加しました。このロックが既にスレッドによって占有されている場合、占有スレッドが現在のスレッドであるかどうかを引き続きチェックします。
再取得するたびに同期状態をプラスする操作が行われますが、リリース時の処理の考え方はどうなりますか?依然として非公平ロックを例としている)コア方法はtryReleaseである:

protected final boolean tryRelease(int releases) {
//1.      1
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
//2.         0 ,      ,  true
free = true;
setExclusiveOwnerThread(null);
}
// 3.        ,  false
setState(c);
return free;
}
コードのロジックはコメントを見てください。再入力ロックのリリースは同期状態が0の時にロックが成功的に解除されます。そうでないとロックが解除されません。もしロックがn回取得されたら、n-1回リリースします。このロックは完全にリリースされずにfalseに戻ります。n回だけ釈放されて、trueに戻ります。
これまでは、RentrantrantLockの再入力性の実現、すなわち同期語義の第一条を理解することができました。
3.公平錠と公平錠
RentrantrantLockは二つのロックをサポートします。公平ロックと非公平ロックです。
公平性とは、ロックを取得することに対して、ロックが公平であれば、ロックの取得順序は要求上の絶対時間順序に適合し、FIFOを満たすべきである。RentrantrantLockの構造方法が無参加の時は構造が非公平ロックで、ソースは次の通りです。

public ReentrantLock() {
sync = new NonfairSync();
}
また、他の方法を提供していますが、ブーメランの値に入ることができます。trueの場合は公平ロック、falseの場合は非公正ロック、ソースは:

public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
上記の非公平ロック取得時(nonfairTryAcquire方法)は、現在の状態を簡単に取得しただけで、いくつかの論理処理を行いましたが、現在の同期キューにスレッドが待っていることは考えられませんでした。
公正ロックの処理ロジックはどうですか?

protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
このコードの論理はnonfairTryAcquireと基本的に一致しています。唯一の違いは、hasQueuedPrdecessorsを追加した論理判定であり、方法名は、現在のノードが同期キューに前駆ノードがあるかどうかを判断するための方法を知ることができます。前駆ノードがあれば、スレッドが現在スレッドより早い要求リソースがあると説明しています。現在のスレッドのリソース要求に失敗しました。現在ノードに前駆ノードがないと、後の論理判断をする必要があります。
公平ロックは、毎回同期キューの最初のノードからロックを取得し、公平性ロックでないと一定ではなく、ロックを解除したばかりのスレッドが再びロックを取得する可能性がある。
公平ロックVS非公正ロック
公平ロックは、同期キューにロックされている最初のノードを取得するたびに、要求リソースの時間における絶対的な順序を保証し、公平ロックを解除したばかりのスレッドではなく、次にこのロックを取得し続けると、他のスレッドがいつまでもロックを取得できなくなり、「空腹」現象を引き起こす可能性がある。
公平なロックは、時間の絶対的な順序を保証するために、頻繁なコンテキスト切り替えが必要であり、公平なロックではなく、一定のコンテキスト切り替えを低減し、性能オーバーヘッドを低減する。したがって、Reentrant Lockはデフォルトで非公平ロックを選択し、一部のコンテキスト切り替えを低減するために、システムのより大きなスループットを保証する。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。