Javaでフェイルファーストの同期方法はありますか?
ここでやろうとしていることを説明するために「フェイルファスト」を使用するのは、用語の選択が不適切だと思います。フェイルファストとは、すぐにロックを取得できないことが障害またはアプリケーション エラーであることを意味します。チェックされていない CCME をスローする cf フェイルファスト イテレータ。これは、一般的なロックによって提供されるセマンティック モデルではなく、ここでは特にそうではありません。より適切な用語は「ノンブロッキング」です。
また、ロックを取得できないためにコード ブロックをサイレントにスキップすることが有用な動作であるかどうかも明確ではありません。ほとんどの場合、アプリケーションは「スキップ」パスが使用されたことを認識する必要があります。
これらの点は別として、プリミティブ オブジェクト ロックを使用してそれを行うことはできません。
(OK、一部の JVM ではこれを行うために使用できるかもしれませんがsun.misc.Unsafe
、それは本当に悪い考えです。コンパイラ、クラス ローダー、またはセキュリティ サンドボックスがUnsafe
API の使用を妨げていることに気付く可能性があります。その上、この API は何の理由もなく「安全ではない」と呼ばれているわけではありません!)
API には、java.util.concurrent.locks.Lock
ブロックせずにロックの取得を試行できるメソッドがあります。具体的には、このtryLock()
メソッドはロックの取得を試み、ロックが使用中の場合はすぐに戻りますfalse
。
ersatz ロックとして使用できる他の高レベルの同時実行クラスがあります。例えばSemaphore
。
または別の言い方をすれば、オブジェクトが既にロックされているかどうかを検出する方法はありますか?
実際、それは少し異なります...そして完全に役立つわけでもありません。確かに、(仮説的に) ロックが保持されているかどうかをテストできます。(実際、Lock
これを明示的にサポートしているクラスもあります。)しかし、ブロックせずにロックを取得できることが保証されているわけではありません。その (間違った) 仮定を行うと、コードに Heisenbug が導入されたことになります。
ロック状態をチェックする組み込みの方法があるのだろうか?
[プリミティブロックを参照していると仮定すると...]
いいえ、ありません。少なくとも、実行中のアプリケーション自体ではありません。(デバッグ エージェントはこれを行うことができますが、アプリケーションがその JVM のデバッグ エージェントと通信するのは現実的ではありません。)
この種のことをしたい/する必要がある場合、アプリケーションのロックメカニズムの変更を伴わない実際のオプションはありません。そういうものだ。