Я реализовал простой профилировщик с JVMTI для отображения вызова на wait()
и notifyAll()
. В качестве тестового примера я использую. производитель, потребительский пример Oracle . У меня есть следующие три события:
- вызывается notifyAll ()
- wait () вызывается
- wait () осталось
Вызов wait()
и когда он был оставлен, он профилируется с использованием событий MonitorEnter
и MonitorExit
. Вызов notifyAll()
профилируется при выходе из метода с именем notifyAll
.
Теперь у меня есть следующие результаты: сначала от самого профилировщика , а второй от Java , где я поместил соответствующий оператор System.out.println
.
// 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()
Есть ли у кого-нибудь объяснение, из-за чего возникает это несоответствие? notifyAll()
вызывается так много раз. Мне сказали, что это может быть связано с ложноположительными ответами на запрос Java к операционной системе.
Запрос notifyAll()
отправляется в операционную систему, и ложно-положительный ответ отправляется, когда кажется, что запрос был успешным. Поскольку notifyAll
регистрируется путем вызова метода профилирования вместо MonitorEnter
, это может объяснить, почему это не происходит с ожиданием.
Я забыл сказать, что я не запускал программы по отдельности, оба журнала имеют одинаковое исполнение.
Дополнительная информация
Первоначально добавлено в качестве ответа, перенесено на вопрос extraneon:
Мне кажется, я выяснил, откуда некоторые дополнительных уведомлений, все, я добавил профилирование контекста метода, в котором вызывается notifyAll:
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
Но даже без этих внешних вызовов существует множество вызовов notifyAll, которые не отображаются в отладке printf.