Perbezaan Halus Antara notify() dan notifyAll()
Walaupun perbezaan utama antara notify() dan notifyAll() terletak pada bilangan benang menunggu yang mereka bangunkan (satu berbanding semua), ini menimbulkan satu lagi soalan:
Mengapa satu utas sentiasa memperoleh semula kunci objek?
Dalam kes umum, notify() dan notifyAll() tidak menyatakan menunggu yang mana benang akan dipilih untuk memperoleh semula kunci. JVM atau penjadual urutan sistem membuat pilihan ini, yang boleh menjadi bukan penentu.
Keperluan untuk notifyAll()
Walau bagaimanapun, menggunakan notify() dalam senario tertentu boleh membawa kepada kebuntuan, seperti yang digambarkan oleh yang berikut contoh:
Kelas Pengeluar/Pengguna dengan notify()
public class ProducerConsumer { private final int MAX_SIZE = 1; // Buffer size private List<Object> buf = new ArrayList<>(); public synchronized void put(Object o) { while (buf.size() == MAX_SIZE) { wait(); } buf.add(o); notify(); } public synchronized Object get() { while (buf.size() == 0) { wait(); } Object o = buf.remove(0); notify(); return o; } }
Senario Deadlock:
Akibatnya, ketiga-tiga utas menunggu selama-lamanya, membawa kepada kebuntuan.
Penyelesaian: notifyAll()
Untuk menyelesaikan kebuntuan ini, seseorang mesti menggunakan notifyAll() dan bukannya notify() dalam kod pengeluar/pengguna. Ini memastikan bahawa semua urutan menunggu dibangkitkan, mengelakkan kebuntuan.
Cadangan:
Untuk kebanyakan senario, notifyAll() ialah kaedah pilihan kerana ia mengelakkan kemungkinan kebuntuan. Jika senario tertentu memerlukan hanya satu urutan menunggu tertentu, maka notify() boleh digunakan dengan berhati-hati.
Atas ialah kandungan terperinci Mengapa Satu Benang Sentiasa Memperoleh Semula Kunci Objek Selepas notify() atau notifyAll()?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!