Rumah  >  Artikel  >  Java  >  Mengapa Satu Benang Sentiasa Memperoleh Semula Kunci Objek Selepas notify() atau notifyAll()?

Mengapa Satu Benang Sentiasa Memperoleh Semula Kunci Objek Selepas notify() atau notifyAll()?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-24 11:38:10385semak imbas

Why Does One Thread Always Reacquire the Object Lock After notify() or notifyAll()?

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:

  1. Penerbit P1 meletakkan objek ke dalam penimbal.
  2. Pengeluar P2 dan Percubaan P3 untuk meletakkan objek tetapi disekat kerana penimbal penuh.
  3. Pengguna C1 cuba mendapatkan objek daripada penimbal.
  4. C1 sedang melaksanakan dan mendapatkan objek, kemudian memberitahu urutan yang menunggu .
  5. P2 atau C2 boleh dibangkitkan oleh pemberitahuan, tetapi kedua-duanya disekat cuba memperoleh semula kunci.
  6. C3 juga disekat cuba mendapatkan kunci.

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn