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; } }
Scénario de blocage :
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!