Menjawab pertanyaan OP
Apa yang bisa saya lakukan untuk membangunkan ini, menunggu dengan palsu tanpa menunggu selamanya untuk acara acak?
, tidak ada bangun palsu yang dapat membangunkan utas menunggu ini!
Terlepas dari apakah wakeups palsu dapat atau tidak bisa terjadi pada platform tertentu, dalam kasus potongan OP itu tidak mungkin untukCondition.await() kembali dan melihat garis "Wake up palsu!" dalam aliran output.
Kecuali Anda menggunakan Java Class Library yang sangat eksotis
Hal ini karena standar, OpenJDK 's ReentrantLock' s metode newCondition()pengembalian yang AbstractQueuedSynchronizer'implementasi s dari Conditioninterface, bersarang ConditionObject(by the way, itu adalah satu-satunya implementasi Conditionantarmuka di perpustakaan kelas ini), dan ConditionObject' s metode await()itu sendiri cek apakah kondisi tidak memegang dan tidak ada bangun palsu dapat memaksa metode ini untuk kembali secara keliru.
Omong-omong, Anda bisa memeriksanya sendiri karena cukup mudah untuk meniru bangun palsu setelah AbstractQueuedSynchronizerimplementasi berbasis-terlibat.
AbstractQueuedSynchronizermenggunakan tingkat rendah LockSupport's parkdan unparkmetode, dan jika Anda menjalankan LockSupport.unparkpada thread menunggu diCondition , tindakan ini tidak dapat dibedakan dari wakeup palsu.
Sedikit refactoring cuplikan 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");
}
}
, dan tidak peduli seberapa keras utas yang tidak parkir (utama) akan mencoba untuk membangunkan utas yang menunggu, Condition.await()metode ini tidak akan pernah kembali dalam kasus ini.
Wakeups palsu pada Conditionmetode yang menunggu dibahas dalam javadoc Conditionantarmuka . Meskipun dikatakan bahwa,
ketika menunggu suatu Kondisi, bangun palsu diizinkan untuk terjadi
dan itu
direkomendasikan bahwa pemrogram aplikasi selalu berasumsi bahwa mereka dapat terjadi dan selalu menunggu dalam satu lingkaran.
tetapi kemudian menambahkan itu
Suatu implementasi gratis untuk menghilangkan kemungkinan wake up palsu
dan AbstractQueuedSynchronizerimplementasi Conditionantarmuka tidak persis seperti itu - menghilangkan segala kemungkinan wakeup palsu .
Ini tentu berlaku untuk ConditionObjectmetode lain yang menunggu.
Jadi kesimpulannya adalah:
kita harus selalu memanggil Condition.awaitloop dan memeriksa apakah kondisinya tidak berlaku, tetapi dengan standar, OpenJDK, Java Class Library tidak pernah bisa terjadi . Kecuali, sekali lagi, Anda menggunakan Java Class Library yang sangat tidak biasa (yang pasti sangat sangat tidak biasa, karena Java Class Library non-OpenJDK lain yang terkenal, yang saat ini hampir punah GNU Classpath dan Apache Harmony , tampaknya memiliki identik dengan implementasi standar Conditionantarmuka)
pthread_cond_wait()pertanyaan sebenarnya adalah "Mengapa pthread_cond_wait memiliki wakeups palsu?" .