Я не думаю, что ваш дамп потока говорит, что ваши два потока "ждут двух разных других мониторов". Я думаю, что это говорит о том, что они оба ждут на одном мониторе, но в двух разных точках кода. Это может быть расположение в стеке, расположение экземпляра объекта или что-то еще. Это отличный документ о анализе дампов стека .
Может ли несколько потоков удерживать блокировку на одном мониторе в Java?
Нет. Ваш дамп стека показывает два потока, заблокированных на одном мониторе в одном и том же месте кода, но в разных фреймах стека - или независимо от того, какое это значение является зависимым от ОС.
Edit:
Я не уверен, почему дамп потока говорит о том, что в обоих потоках заблокирована строка, поскольку это разрешено только в том случае, если они находятся в методе wait()
. Я заметил, что вы ссылаетесь на версию 1.6.5. Это действительно версия, которую вы используете? В версии 2.3.6 (которая может быть самой последней) строка 1725 фактически является wait
.
1722 synchronized (this) {
1723 while (currentlyLoading.contains(id)) {
1724 try {
1725 wait();
1726 } catch (InterruptedException e) {
Вы также можете видеть этот вид трассировки стека, даже если это была эксклюзивная synchronized
блокировка. Например, следующий дамп стека в Linux предназначен для двух потоков, заблокированных для одного и того же объекта из одной и той же строки кода, но в двух разных случаях метода Runnable.run()
. Вот моя глупая маленькая тестовая программа . Обратите внимание, что номера записей на мониторе отличаются, даже если это один и тот же замок и один и тот же номер строки кода.
"Thread-1" prio=10 tid=0x00002aab34055c00 nid=0x4874
waiting for monitor entry [0x0000000041017000..0x0000000041017d90]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aab072a1318> (a java.lang.Object)
at com.mprew.be.service.auto.freecause.Foo$OurRunnable.run(Foo.java:38)
- locked <0x00002aab072a1318> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:619)
"Thread-0" prio=10 tid=0x00002aab34054c00 nid=0x4873
waiting for monitor entry [0x0000000040f16000..0x0000000040f16d10]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aab072a1318> (a java.lang.Object)
at com.mprew.be.service.auto.freecause.Foo$OurRunnable.run(Foo.java:38)
- locked <0x00002aab072a1318> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:619)
На моем Mac формат другой, но опять-таки число после «записи монитора» не совпадает для того же номера строки.
"Thread-2" prio=5 tid=7f8b9c00d000 nid=0x109622000
waiting for monitor entry [109621000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f3192fb0> (a java.lang.Object)
at com.mprew.be.service.auto.freecause.Foo$OurRunnable.run(Foo.java:38)
- locked <7f3192fb0> (a java.lang.Object)
"Thread-1" prio=5 tid=7f8b9f80d800 nid=0x10951f000
waiting for monitor entry [10951e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f3192fb0> (a java.lang.Object)
at com.mprew.be.service.auto.freecause.Foo$OurRunnable.run(Foo.java:38)
- locked <7f3192fb0> (a java.lang.Object)
Этот документ Oracle описывает это значение следующим образом:
Диапазон адресов, который дает оценку действительной области стека для потока