Question

Je l'ai mis en œuvre simple profileur avec JVMTI pour afficher l'invocation sur wait() et notifyAll(). En cas de test, je me sers du. exemple producteur-consommateur de Oracle. Je les trois événements suivants:

  • notifyAll () est appelée
  • wait () est appelée
  • attente () reste

L'invocation de wait() et quand sa gauche il en utilisant les profilés événements MonitorEnter et MonitorExit. L'invocation de notifyAll() est profilée lorsqu'une méthode avec le nom notifyAll est sorti.

Maintenant, j'ai les résultats suivants, première est du profileur lui-même et le seconde est de Java , où je l'ai placé la déclaration de System.out.println appropriée.

    // Profiler:
    Thread-1 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 left wait()
    Thread-1 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 left wait()
    Thread-1 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 left wait()
    Thread-1 invoked notifyAll()

    // Java:
    Thread-0 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-1 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 invoked notifyAll()
    Thread-0 invoked notifyAll()
    Thread-1 invoked wait()
    Thread-1 invoked notifyAll()

Quelqu'un at-il une explication de ce que cet écart provient? notifyAll() est appelé tant de fois. On m'a dit que cela pourrait être dû à des réponses faussement positives de la demande de Java au système d'exploitation.

Une demande de notifyAll() il envoyé au système d'exploitation et une réponse de faux positifs est envoyé, où il semble que la demande était sucessfull. Depuis notifyAll est connecté par l'invocation de la méthode de profilage au lieu de MonitorEnter pourrait expliquer pourquoi cela ne se produit pas avec attente.

J'ai oublié de dire, je ne l'ai pas exécuter les programmes séparément, les deux journaux sont de la même exécution.

Information additionnelle

A l'origine ajouté en réponse, déplacé à la question par extraneon:

Je pense que j'ai découvert où certains des notifyAll supplémentaires viennent, j'ai ajouté le profilage du contexte de la méthode dans laquelle notifyAll est appelée:

723519: Thread-1 invoked notifyAll() in Consumer.take
3763279: Thread-0 invoked notifyAll() in Producer.put
4799016: Thread-0 invoked notifyAll() in Producer.put
6744322: Thread-0 invoked notifyAll() in Producer.put
8450221: Thread-0 invoked notifyAll() in Producer.put
10108959: Thread-0 invoked notifyAll() in Producer.put
39278140: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
40725024: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
42003869: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
58448450: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
60236308: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
61601587: Thread-1 invoked notifyAll() in java.util.ResourceBundle.endLoading
70489811: Thread-1 invoked notifyAll() in Consumer.take
75068409: Thread-1 invoked wait() in Drop.take
75726202: Thread-1 left wait() in Drop.take
77035733: Thread-1 invoked notifyAll() in Consumer.take
81264978: Thread-1 invoked notifyAll() in Consumer.take
85810491: Thread-1 invoked wait() in Drop.take
86477385: Thread-1 left wait() in Drop.take
87775126: Thread-1 invoked notifyAll() in Consumer.take

Mais même sans ces appels externes, il y a plteny des appels notifyAll qui ne se présentent pas dans le débogage printf.

Était-ce utile?

La solution

J'ai passé quelque temps à analyser producteur-consommateur par exemple fourni par Oracle et votre sortie (profileur et programme Java). Il y a des choses étranges sur vos sorties en dehors du plusieurs notifyAll() inattendu:

  1. nous devrions nous attendre la méthode d'attente () pour exécuter 4 fois (le tableau de String manipulé par le producteur dispose de 4 éléments). Le résultat de vos émissions profileurs qu'il n'exécuté trois fois.

  2. Une autre chose qui est tout à fait étrange est la numérotation des fils dans la sortie du profileur. L'exemple a deux fils, mais votre profileur exécute tout le code dans un thread, à savoir Thread-1, alors que Thread-0 qu'exécuter notifyAll().

  3. Le code exemple fourni est correctement programmé dans une perspective simultanée et la perspective linguistique: wait() et notifyAll() sont des méthodes synchronisées pour assurer le contrôle de l'écran; condition d'attente est dans une boucle de while avec les notifie correctement placés à la fin des méthodes. Cependant, je remarque que le bloc de catch (InterruptedException e) est vide, ce qui signifie que si le fil qui est en attente est interrompue, la méthode notifyAll() sera exécutée. Cela peut être une cause de plusieurs notifyAll() inattendues.

En conclusion, sans effectuer quelques modifications dans le code et effectuer quelques tests supplémentaires, il ne sera pas facile de savoir où le problème vient.

Comme une note de côté, je vais laisser ce lien Création d'un agent Déboguer et avec JVMTI pour les curieux qui veulent jouer avec JVMTI.

Autres conseils

Si vous avez une condition de course dans votre code, un profileur peut ralentir suffisamment de code pour afficher ou masquer une erreur dans votre code. (J'aime courir mon programme dans un profileur, juste pour montrer les conditions de course.)

notifyAll () ne notifie attente () uant threads, appelant wait () après la notifyAll () est susceptible d'entraîner le manque Notify. à-dire son apatride, il ne sait pas que vous avez appelé avertira avant.

Si vous ralentissez votre application, le notifyAll () peut être retardée jusqu'à ce que l'attente () commence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top