OPの質問に答える
ランダムなイベントを永遠に待たずに、この待機を誤って起動するために私は何ができますか?
、 偽のウェイクアップがこの待機中のスレッドをウェイクアップすることません!
特定のプラットフォームで偽のウェイクアップが発生するかどうかに関係なく、OPのスニペットの場合、それは明らかに不可能です。のためにCondition.await()
返すようにしてラインを参照するには、「スプリアスウェイクアップを!」出力ストリーム内。
あなたが非常にエキゾチックなものを使用しているのでない限り Javaクラスライブラリ
これは、標準的なためであるOpenJDKのさんReentrantLock
の方法は、newCondition()
返しAbstractQueuedSynchronizer
ののを実装Condition
ネストインタフェース、ConditionObject
(方法によって、それが唯一の実装でありCondition
、このクラスライブラリのインターフェイス)、及びConditionObject
の方法await()
条件がないかどうか自体をチェックします保持し、偽のウェイクアップによってこのメソッドが誤って戻ることを強制することはできません。
ちなみに、AbstractQueuedSynchronizer
ベースの実装が含まれていると、偽のウェイクアップをエミュレートするのは非常に簡単なので、自分で確認できます。
AbstractQueuedSynchronizer
低レベルLockSupport
のpark
とunpark
メソッドを使用します。LockSupport.unpark
しているスレッドCondition
、このアクションは偽のウェイクアップと区別できません。
OPのスニペットを少しリファクタリングし、
public class Spurious {
private static class AwaitingThread extends Thread {
@Override
public void run() {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
private static final int AMOUNT_OF_SPURIOUS_WAKEUPS = 10;
public static void main(String[] args) throws InterruptedException {
Thread awaitingThread = new AwaitingThread();
awaitingThread.start();
Thread.sleep(10000);
for(int i =0 ; i < AMOUNT_OF_SPURIOUS_WAKEUPS; i++)
LockSupport.unpark(awaitingThread);
Thread.sleep(10000);
if (awaitingThread.isAlive())
System.out.println("Even after " + AMOUNT_OF_SPURIOUS_WAKEUPS + " \"spurious wakeups\" the Condition is stil awaiting");
else
System.out.println("You are using very unusual implementation of java.util.concurrent.locks.Condition");
}
}
、およびunparking(main)スレッドが待機中のスレッドを起こそうとするのがどれほど困難であってCondition.await()
も、この場合、メソッドは決して戻りません。
待機中のメソッドに対する誤ったウェイクアップCondition
については、インターフェースのjavadocでCondition
説明されています。とはいえ、
条件を待っているときに、偽のウェイクアップが発生することが許可されます
そしてそれ
アプリケーションプログラマーは常に発生する可能性があると想定し、常にループで待機することをお勧めします。
しかし、それは後でそれを追加します
実装は、偽のウェイクアップの可能性を自由に削除できます
およびAbstractQueuedSynchronizer
のCondition
インターフェースの実装はまさにそれを行います- 偽のウェイクアップの可能性を排除します。
これは確かに他にも当てはまります ConditionObject
のの待機中のメソッドにます。
だから、結論は次のとおりです。
常にCondition.await
ループで呼び出し、条件が満たされていないかどうかを確認する必要がありますが、標準のOpenJDKでは、Javaクラスライブラリが発生することはありません。繰り返しになりますが、非常に珍しいJavaクラスライブラリを使用しない限り(これは非常に珍しいはずです。現在、ほとんど絶滅している別の有名な非OpenJDK Javaクラスライブラリは、GNU ClasspathとApache Harmonyであり、Condition
インターフェースの標準実装と同一であるようです)
pthread_cond_wait()
、実際の質問を使用するJVMの場合、「なぜpthread_cond_waitに誤ったウェイクアップがあるのですか?」。