11

一見単純な問題: 私は を持っており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()が、中断されない待機は必要ありません。誤って中断されない待機だけです。代替手段はありますか?

4

2 に答える 2

7

「偽の割り込み」ではなく「偽のウェイクアップ」です。スプリアス ウェイクアップ中にスローされる InterruptedException はありません。コメントで言うように: スレッドは起動しますが、割り込みフラグは設定されていません。

于 2012-08-28T18:19:12.887 に答える
3

APIについて考えてみると、主に呼び出し元が「スプリアス」と「通常」を区別する方法がなく、メソッドが役に立たないSemaphore.acquire()ため、スプリアス ウェイクアップが不可能であることがわかると思います。

于 2012-08-28T18:24:02.707 に答える