Maison > Java > javaDidacticiel > Pourquoi un thread réacquiert-il toujours le verrouillage d'objet après notify() ou notifyAll() ?

Pourquoi un thread réacquiert-il toujours le verrouillage d'objet après notify() ou notifyAll() ?

Mary-Kate Olsen
Libérer: 2024-11-24 11:38:10
original
446 Les gens l'ont consulté

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

La distinction subtile entre notify() et notifyAll()

Alors que la principale différence entre notify() et notifyAll() réside dans le nombre de threads en attente qu'ils réveillent (un contre tous), cela soulève une autre question :

Pourquoi un fil toujours réacquérir le verrou de l'objet ?

Dans le cas général, notify() et notifyAll() ne précisent pas quel thread en attente sera sélectionné pour réacquérir le verrou. Le planificateur de threads JVM ou système effectue cette sélection, qui peut être non déterministe.

La nécessité de notifyAll()

Cependant, l'utilisation de notify() dans certains scénarios peut conduire à une impasse, comme l'illustre l'exemple suivant :

Classe Producteur/Consommateur avec 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;
    }
}
Copier après la connexion

Scénario de blocage :

  1. Le producteur P1 place un objet dans le tampon.
  2. Le producteur P2 et P3 tentent de mettre des objets mais sont bloqués car le tampon est plein.
  3. Consommateur C1 tente d'obtenir un objet du tampon.
  4. C1 est en cours d'exécution et récupère l'objet, puis notifie un thread en attente.
  5. P2 ou C2 peuvent être réveillés par la notification, mais ils sont tous les deux bloqué en essayant de réacquérir le verrou.
  6. C3 est également bloqué en essayant d'acquérir le verrou. lock.

En conséquence, les trois threads attendent indéfiniment, conduisant à une impasse.

La solution : notifyAll()

Pour résoudre cette impasse, il faut utiliser notifyAll() au lieu de notify() dans le code producteur/consommateur. Cela garantit que tous les threads en attente sont réveillés, évitant ainsi les blocages.

Recommandation :

Pour la plupart des scénarios, notifyAll() est la méthode préférée car elle évite les blocages potentiels. Si le scénario spécifique nécessite de réveiller un seul thread en attente spécifique, alors notify() peut être utilisé avec prudence.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal