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 Condition
ara yüzü, iç içeConditionObject
(bu arada, sadece uygulamasıdır Condition
bu 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, AbstractQueuedSynchronizer
tabanlı uygulama dahil edildiğinde sahte uyandırma taklit etmek oldukça kolay olduğu için kendiniz kontrol edebilirsiniz .
AbstractQueuedSynchronizer
düşük seviyeli kullanır LockSupport
'spark
ve unpark
yö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 Condition
yö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 Condition
arayüzü tam olarak bunu yapar - sahte uyandırma olasılığını ortadan kaldırır .
Bu elbette diğerlerinin ConditionObject
beklediği yöntemler için de geçerlidir .
Yani, sonuç, geçerli:
her zaman Condition.await
dö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 Condition
arayü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?" .