一見単純な問題: 私は を持っておりjava.util.concurrent.Semaphore
、 を使用して許可を取得したいと考えていacquire()
ます。
このメソッドは、スレッドが中断された場合acquire()
にスローするように指定されています。InterruptedException
現在のスレッドの場合:
- このメソッドへのエントリで割り込みステータスが設定されます。また
- 許可を待っている間に中断され、
次に InterruptedException がスローされ、現在のスレッドの中断ステータスがクリアされます。
ただし、スローされる可能性のあるメソッドの通常のパターンはInterruptedException
、スレッドが中断されているのと同じように見える誤ったウェイクアップの影響を受ける可能性があるため、それらをループで呼び出すことです。たとえば、のドキュメントにObject.wait(long)
は次のように記載されています。
スレッドは、通知、中断、またはタイムアウトなしでウェイクアップすることもできます。これは、いわゆるスプリアス ウェイクアップです。これが実際に発生することはめったにありませんが、アプリケーションは、スレッドが起動される原因となったはずの条件をテストし、条件が満たされない場合は待機し続けることで、これを防ぐ必要があります。つまり、待機は常にループで発生する必要があります。
問題は、Semaphore.acquire()
同じ種類のスプリアス ウェイクアップの影響を受けるかどうかです。論理的な答えは「いいえ」ですが、その証拠を見つけることができず、実際、証拠は別の方向を指しているようです.
のソースをSemaphore
見ると、実際の取得を に委譲しているように見えます。ソースAbstractQueuedSynchronizer
によれば、これは に委譲しています。LockSupport.park()
のドキュメントでLockSupport.park()
は偽のウェイクアップについて明示的に言及されていますが、 の実装はAbstractQueuedSynchronizer.doAcquireInterruptably()
単にチェックThread.interrupted()
してからスローするように見えますInterruptedException
。
それで、私が何かを見逃していない限り(これは非常に可能性があります)、誤ってスローSemaphore.acquire()
できるように見えますか?InterruptedException
あれは正しいですか?もっと重要なのは、それについて私にできることはありますか?を使用できますSemaphore.acquireUninterruptably()
が、中断されない待機は必要ありません。誤って中断されない待機だけです。代替手段はありますか?