Melihat berbagai pertanyaan terkait penguncian dan (hampir) selalu menemukan 'loop karena istilah wakeups palsu' 1 Saya bertanya-tanya, adakah yang pernah mengalami wakeup semacam itu (misalnya, dengan asumsi lingkungan hardware / software yang layak)?
Saya tahu istilah 'palsu' berarti tidak ada alasan yang jelas tetapi apa yang bisa menjadi alasan untuk acara semacam itu?
( 1 Catatan: Saya tidak mempertanyakan praktik perulangan.)
Sunting: Pertanyaan pembantu (bagi mereka yang suka contoh kode):
Jika saya memiliki program berikut, dan saya menjalankannya:
public class Spurious {
public static void main(String[] args) {
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();
}
}
}
Apa yang bisa saya lakukan untuk membangunkan ini await
dengan palsu tanpa menunggu selamanya untuk acara acak?
java
multithreading
locking
spurious-wakeup
akarnokd
sumber
sumber
pthread_cond_wait()
pertanyaan sebenarnya adalah "Mengapa pthread_cond_wait memiliki wakeups palsu?" .Jawaban:
Artikel Wikipedia tentang wake up palsu memiliki berita gembira ini:
Rangkuman : Jika ada proses Linux yang diberi tanda, masing-masing utasnya akan menikmati bangun yang bagus dan panas .
Saya membelinya. Itu adalah pil yang lebih mudah untuk menelan daripada alasan "itu untuk kinerja" yang sering diberikan.
sumber
futex()
Panggilan yang mendasarinya kembaliEINTR
, tetapi nilai kembali itu tidak menggelembung ke tingkat berikutnya. Penelepon pthread karena itu harus memeriksa invarian. Apa yang mereka katakan adalah bahwa ketikapthread_cond_wait()
kembali, Anda harus memeriksa kembali kondisi loop Anda (invarian), karena penantian mungkin telah dibangunkan secara palsu. Menerima sinyal selama panggilan sistem adalah salah satu penyebab yang mungkin, tetapi itu bukan satu-satunya.pthread
perpustakaan bisa menyediakan invarian sendiri dan logika pemeriksaan sendiri untuk menghilangkan bangun palsu, daripada menyerahkan tanggung jawab itu kepada pengguna. Itu akan (mungkin) memiliki dampak kinerja yang diklaim.Saya memiliki sistem produksi yang menunjukkan perilaku ini. Utas menunggu sinyal bahwa ada pesan dalam antrian. Dalam periode sibuk, hingga 20% dari bangun adalah palsu (yaitu ketika bangun tidak ada dalam antrian). Utas ini adalah satu-satunya konsumen pesan. Ini berjalan pada kotak Linux SLES-10 8-prosesor dan dibangun dengan GCC 4.1.2. Pesan berasal dari sumber eksternal dan diproses secara tidak sinkron karena ada masalah jika sistem saya tidak membacanya dengan cukup cepat.
sumber
Untuk menjawab pertanyaan dalam titile - Ya! itu memang terjadi. Meskipun artikel Wiki menyebutkan banyak tentang wakeups palsu penjelasan yang bagus untuk hal yang sama yang saya temui adalah sebagai berikut -
Saya membaca jawaban ini dari Sumber dan merasa cukup masuk akal. Baca juga
Kebangkitan palsu di Jawa dan cara menghindarinya .
PS: Tautan di atas adalah ke blog pribadi saya yang memiliki detail tambahan tentang bangun palsu.
sumber
Cameron Purdy menulis posting blog beberapa waktu lalu tentang terkena masalah wakeup palsu. Jadi ya, itu terjadi
Saya menduga itu dalam spesifikasi (karena kemungkinan) karena keterbatasan beberapa platform yang digunakan Java? meskipun saya mungkin salah!
sumber
Tambahkan saja ini. Ya itu terjadi dan saya menghabiskan tiga hari mencari penyebab masalah multi-threading pada mesin 24 core (JDK 6). 4 dari 10 eksekusi mengalami hal itu tanpa pola apa pun. Ini tidak pernah terjadi pada 2 inti atau 8 core.
Mempelajari beberapa materi online dan ini bukan masalah Java tetapi perilaku umum yang jarang tetapi diharapkan.
sumber
https://stackoverflow.com/a/1461956/14731 berisi penjelasan yang sangat baik tentang mengapa Anda perlu berjaga-jaga terhadap bangun palsu bahkan jika sistem operasi yang mendasarinya tidak memicu mereka. Sangat menarik untuk dicatat bahwa penjelasan ini berlaku di berbagai bahasa pemrograman, termasuk Java.
sumber
Menjawab pertanyaan OP
, 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 untuk
Condition.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 metodenewCondition()
pengembalian yangAbstractQueuedSynchronizer
'implementasi s dariCondition
interface, bersarangConditionObject
(by the way, itu adalah satu-satunya implementasiCondition
antarmuka di perpustakaan kelas ini), danConditionObject
' s metodeawait()
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 rendahLockSupport
'spark
danunpark
metode, dan jika Anda menjalankanLockSupport.unpark
pada thread menunggu diCondition
, tindakan ini tidak dapat dibedakan dari wakeup palsu.Sedikit refactoring cuplikan OP,
, 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 javadocCondition
antarmuka . Meskipun dikatakan bahwa,dan itu
tetapi kemudian menambahkan itu
dan
AbstractQueuedSynchronizer
implementasiCondition
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 standarCondition
antarmuka)sumber