Dopo aver eseguito wait (), quanto tempo attende un thread se non riceve una notifica da altri thread?

Aug 16 2020

Nell'esempio seguente, poiché il thread principale non riceve una notifica dal thread figlio, dovrebbe attendere per sempre. Ma il thread principale viene eseguito e l'output dell'esempio seguente è:

c
l
total: 19900

Perché il thread principale viene eseguito?

public class ThreadX extends Thread {
    static int total = 0;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 200; i++) {
                total = total + i;
            }
            System.out.println("c");

        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadX t = new ThreadX();

        t.start();
        synchronized (t) {
            t.wait();
            System.out.println("l");
        }

        System.out.println("total: " + total);

    }
}

Risposte

10 akuzminykh Aug 16 2020 at 09:58

Rispondi al corpo della domanda

Check out Thread#join(long):

[...] Quando un thread termina, il this.notifyAllmetodo viene invocato. [...]

Si noti che Thread#join()chiama quella funzione con 0, che significa per sempre.

[...] Un timeout di 0 significa aspettare per sempre.

Quindi nel tuo caso qui tchiama solo notifyAllquando termina, il che notifica il thread principale che è in attesa t.


Questo comportamento non intuitivo è il motivo per cui scrivono quanto segue nella documentazione:

Si raccomanda di non utilizzare le applicazioni wait, notifyo notifyAllsu Threadistanze.

Rispondi al titolo della domanda

Check out Object#wait(o JLS (17.2.1. Wait) ):

Un thread può attivarsi senza essere avvisato, interrotto o scaduto, un cosiddetto risveglio spurio. Sebbene ciò si verifichi raramente nella pratica, le applicazioni devono proteggersi da esso verificando la condizione che avrebbe dovuto causare il risveglio del thread e continuando ad attendere se la condizione non è soddisfatta.

Quindi i thread in Java possono attivarsi in qualsiasi momento. Un risveglio spurio non è molto probabile ma può accadere.