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 Condition
interface, bersarang ConditionObject
(by the way, itu adalah satu-satunya implementasi Condition
antarmuka 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 AbstractQueuedSynchronizer
implementasi berbasis-terlibat.
AbstractQueuedSynchronizer
menggunakan tingkat rendah LockSupport
's park
dan unpark
metode, dan jika Anda menjalankan LockSupport.unpark
pada 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 Condition
metode yang menunggu dibahas dalam javadoc Condition
antarmuka . 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 AbstractQueuedSynchronizer
implementasi Condition
antarmuka tidak persis seperti itu - menghilangkan segala kemungkinan wakeup palsu .
Ini tentu berlaku untuk ConditionObject
metode lain yang menunggu.
Jadi kesimpulannya adalah:
kita harus selalu memanggil Condition.await
loop 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 Condition
antarmuka)
pthread_cond_wait()
pertanyaan sebenarnya adalah "Mengapa pthread_cond_wait memiliki wakeups palsu?" .