ReentrantLockは、構造とは異なり、構造化されsynchronized
ていません。つまり、ロックにブロック構造を使用する必要はなく、メソッド間でロックを保持することもできます。例:
private ReentrantLock lock;
public void foo() {
...
lock.lock();
...
}
public void bar() {
...
lock.unlock();
...
}
このようなフローは、構成内の単一のモニターを介して表すことは不可能synchronized
です。
それとは別に、タイムアウトをReentrantLock
サポートするロックポーリングと割り込み可能なロック待機をサポートします。また、構成可能な公平性ポリシーReentrantLock
をサポートしているため、より柔軟なスレッドスケジューリングが可能です。
このクラスのコンストラクターは、オプションの公平性パラメーターを受け入れます。設定するtrue
と、競合状態で、ロックは最も長く待機しているスレッドへのアクセスを許可することを優先します。それ以外の場合、このロックは特定のアクセス順序を保証しません。多くのスレッドによってアクセスされるフェアロックを使用するプログラムは、デフォルト設定を使用するプログラムよりも全体的なスループットが低くなる可能性があります(つまり、低速です。多くの場合、はるかに低速です)が、ロックを取得して飢餓の欠如を保証するための時間の変動は小さくなります。ただし、ロックの公平性はスレッドスケジューリングの公平性を保証するものではないことに注意してください。したがって、フェアロックを使用する多くのスレッドの1つは、他のアクティブなスレッドが進行しておらず、現在ロックを保持していないときに、連続して複数回取得する可能性があります。また、時間制限がないことに注意してくださいtryLock
メソッドは公平性の設定を尊重しません。他のスレッドが待機している場合でも、ロックが使用可能であれば成功します。
ReentrantLock
また、よりスケーラブルであり、より高い競合の下ではるかに優れたパフォーマンスを発揮する可能性があります。これについて詳しくは、こちらをご覧ください。
ただし、この主張には異議が唱えられています。次のコメントを参照してください。
再入可能ロックテストでは、毎回新しいロックが作成されるため、排他的ロックはなく、結果のデータは無効になります。また、IBMリンクは、基礎となるベンチマークのソースコードを提供していないため、テストが正しく実行されたかどうかを特徴付けることは不可能です。
いつsを使うべきですReentrantLock
か?そのdeveloperWorksの記事によると...
synchronized
答えは非常に簡単です。時限ロック待機、割り込み可能なロック待機、非ブロック構造化ロック、複数の条件変数、ロックポーリングなど、実際に提供されないものが必要な場合に使用します。ReentrantLock
また、スケーラビリティの利点もあります。実際に高い競合が発生する状況がある場合は、これを使用する必要がありますが、synchronized
ブロックの大部分は、高い競合は言うまでもなく、ほとんど競合を示さないことに注意してください。使用する場合は単に「パフォーマンスが向上する」と想定するのではなく、同期が不十分であることが判明するまで同期を使用して開発することをお勧めします。ReentrantLock
。これらは上級ユーザー向けの高度なツールであることを忘れないでください。(そして、真に上級のユーザーは、単純なツールが不十分であると確信するまで、見つけることができる最も単純なツールを好む傾向があります。)いつものように、最初に正しく作成してから、高速化する必要があるかどうかを心配します。
近い将来、より関連性が高くなる最後の側面の1つは、Java15とProjectLoomに関係しています。ReentrantLock
仮想スレッドの(新しい)世界では、基盤となるスケジューラーは、それよりもはるかにうまく機能することができsynchronized
ます。これは、少なくとも最初のJava 15リリースでは当てはまりますが、後で最適化される可能性があります。
現在のLoomの実装では、仮想スレッドは2つの状況で固定できます。スタックにネイティブフレームがある場合(Javaコードがネイティブコード(JNI)を呼び出してからJavaを呼び出す場合)と、synchronized
ブロックまたはメソッド内の場合です。 。そのような場合、仮想スレッドをブロックすると、それを運ぶ物理スレッドがブロックされます。ネイティブ呼び出しが完了するか、モニターが解放されると(synchronized
ブロック/メソッドが終了すると)、スレッドの固定が解除されます。
で保護された一般的なI/O操作がある場合はsynchronized
、モニターをに置き換えて、モニターReentrantLock
によるピン留めを修正する前でも、アプリケーションがLoomのスケーラビリティの向上を十分に活用できるようにします(または、StampedLock
可能であれば、より高性能を使用します)。 。