OP sorusunu cevaplama
Sonsuza kadar rastgele bir olay beklemeden bunu uyandırmak için ne yapabilirim?
, hiçbir sahte uyandırma bu bekleyen iplik uyanamaz!
Sahte uyandırma işlemlerinin belirli bir platformda gerçekleşip gerçekleşmeyeceğine bakılmaksızın, OP snippet'inde "Sahte uyandırma!" Satırını geri döndürmek ve görmek imkansızdır . Condition.await()çıkış akışında.
Çok egzotik Java Sınıf Kütüphanesi kullanmadığınız sürece
Bunun nedeni standardıdır OpenJDK 'ın ReentrantLock' nin yöntemi newCondition()döndürüyor AbstractQueuedSynchronizer's uygulama Conditionara yüzü, iç içeConditionObject (bu arada, sadece uygulamasıdır Conditionbu sınıf kitaplığında arayüzünün) ve ConditionObject' nin yöntemi await()koşulu yok olmadığını kendisi kontrol eder hiçbir sahte uyandırma bu yöntemi yanlışlıkla geri dönmeye zorlayamaz.
Bu arada, AbstractQueuedSynchronizertabanlı uygulama dahil edildiğinde sahte uyandırma taklit etmek oldukça kolay olduğu için kendiniz kontrol edebilirsiniz .
AbstractQueuedSynchronizerdüşük seviyeli kullanır LockSupport'spark ve unparkyöntemleri ve eğer çağırmak LockSupport.unparküzerinde bekleyen bir iş parçacığı üzerinde Condition, bu eylem bir sahte uyandırma ayırt edilemez.
OP'nin snippet'ini biraz yeniden düzenleyerek,
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");
}
}
ve park etme (ana) iş parçacığının bekleyen iş parçacığı ne kadar zor olursa olsun, Condition.await()yöntem bu durumda geri dönmeyecektir.
Bekleyen Conditionyöntemlerle ilgili sahte uyandırma işlemleri, javadoc arayüzünde tartışıldıCondition . Her ne kadar bunu söylese de,
bir Koşul üzerinde beklerken sahte bir uyanmanın gerçekleşmesine izin verilir
ve şu
uygulama programcılarının her zaman oluşabileceklerini varsaymaları ve böylece her zaman bir döngüde beklemeleri önerilir.
ama daha sonra
Sahte uyandırma olasılığını ortadan kaldırmak için bir uygulama ücretsizdir
ve AbstractQueuedSynchronizer's Conditionarayüzü tam olarak bunu yapar - sahte uyandırma olasılığını ortadan kaldırır .
Bu elbette diğerlerinin ConditionObjectbeklediği yöntemler için de geçerlidir .
Yani, sonuç, geçerli:
her zaman Condition.awaitdöngüyü çağırmalı ve koşulun tutulup tutulmadığını kontrol etmeliyiz , ancak standart, OpenJDK ile Java Sınıf Kütüphanesi asla gerçekleşemez . Yine, çok alışılmadık Java Sınıf Kütüphanesi (bu çok çok sıradışı olmalı, çünkü şu anda neredeyse tükenmiş GNU Sınıfyolu ve Apache Harmony gibi iyi bilinen başka bir OpenJDK Java Sınıf Kütüphanesi, standart Conditionarayüz uygulamasına özdeş görünüyor )
pthread_cond_wait()gerçek soruyu kullanan JVM'ler için "Neden pthread_cond_wait'te sahte uyandırma var?" .