Pourquoi les wait()
y notify()
Les méthodes déclarées dans le Object
plutôt que la classe Thread
classe ?
Réponses
Trop de publicités?En effet, vous attendez qu'un objet donné (ou plus précisément, son moniteur) utilise cette fonctionnalité.
Je pense que vous vous trompez sur le fonctionnement de ces méthodes. Elles ne sont pas simplement au niveau de la granularité du Thread, c'est-à-dire qu'il est no un cas de simple appel wait()
et être réveillé par l'appel suivant à notify()
. Au contraire, vous appelez toujours wait()
sur un objet spécifique, et ne sera réveillé que par des appels à notify
sur cet objet .
C'est une bonne chose car, dans le cas contraire, les primitives de concurrence ne pourraient pas s'adapter ; cela reviendrait à avoir des espaces de noms globaux, puisque tout appel à notify()
n'importe où dans votre programme aurait le potentiel de foutre en l'air tout code concurrent, car ils réveilleraient tous les threads bloquant sur une wait()
appel. D'où la raison pour laquelle vous les appelez sur un objet spécifique ; cela donne un contexte sur lequel la paire wait-notify peut opérer, donc quand vous appelez myBlockingObject.notify()
sur un objet privé, vous pouvez être sûr que vous ne réveillerez que les threads qui ont appelé les méthodes d'attente dans votre classe. Un thread Spring qui serait en train d'attendre un autre objet ne sera pas réveillé par cet appel, et vice versa.
Edit : Ou pour aborder la question d'un autre point de vue - je suppose, d'après votre question, que vous pensiez obtenir une poignée sur le fil d'attente et appeler notify()
sur ce fil pour le réveiller. La raison pour laquelle ce n'est pas fait de cette façon, est que vous devriez faire beaucoup de ménage vous-même. Le thread qui va attendre devrait publier une référence à lui-même quelque part où les autres threads pourraient le voir ; cela devrait être correctement synchronisé pour assurer la cohérence et la visibilité. Et lorsque vous voulez réveiller un thread, vous devez vous emparer de cette référence, le réveiller et la supprimer de l'endroit où vous l'avez lue. Il y a beaucoup plus d'échafaudage manuel impliqué, et beaucoup plus de chance de se tromper (surtout dans un environnement concurrent) comparé à un simple appel à myObj.wait()
dans le fil conducteur et ensuite myObj.notify()
dans le fil de discussion sur le Waker.
La raison la plus simple et la plus évidente est que tout objet (pas seulement un fil) peut être le moniteur d'un thread. Les fonctions wait et notify sont appelées sur le moniteur. Le thread en cours d'exécution vérifie avec le moniteur. Les méthodes wait et notify sont donc dans Object et non dans Thread.
Parce qu'un seul thread à la fois peut posséder le moniteur d'un objet et ce moniteur est ce sur quoi les threads attendent ou notifient. Si vous lisez le javadoc para Object.notify()
y Object.wait()
il est décrit en détail.
Le mécanisme de synchronisation implique un concept - le moniteur d'un objet. Lorsque wait() est appelé, le moniteur est demandé et la poursuite de l'exécution est suspendue jusqu'à ce que le moniteur soit acquis ou qu'une InterruptedException se produise. Lorsque notify() est appelé, le moniteur est libéré.
Prenons un scénario si wait() et notify() étaient placés dans la classe Thread au lieu de la classe Object. A un moment donné dans le code, currentThread.wait()
est appelé et ensuite un objet anObject
est accessible.
//.........
currentThread.wait();
anObject.setValue(1);
//.........
Lorsque currentThread.wait() est appelé, le moniteur de currentThread
est demandé et aucune autre exécution n'est effectuée jusqu'à ce que le moniteur soit acquis ou qu'une InterruptedException se produise. Maintenant, pendant l'état d'attente, si une méthode foo()
d'un autre objet anotherObject
résidant à currentThread
est appelé à partir d'un autre thread, il est bloqué même si la méthode appelée foo()
n'a pas accès anObject
. Si la première méthode wait() a été appelée sur anObject
au lieu du thread lui-même, d'autres appels de méthodes (n'accédant pas à l'information de l anObject
) sur des objets résidant dans le même thread ne seraient pas bloqués.
Ainsi, l'appel des méthodes wait() et notify() sur la classe Object (ou ses sous-classes) fournit une plus grande concurrence et c'est pourquoi ces méthodes sont dans la classe Object, et non dans la classe Thread.
Lire aquí pour une explication de wait and notify.
Il serait toutefois préférable d'éviter ces éléments dans vos applications et d'utiliser les nouvelles versions de la norme java.util.concurrent paquet.