Я заметил что-то очень странное вчера.Кажется, что два потока вводят два синхронизированных блока, блокирующих один и тот же объект одновременно.
Класс (MyClass
), содержащий соответствующий код, выглядит примерно так:
private static int[] myLock = new int[0];
protected static int methodA(final long handle, final byte[] sort) {
synchronized (myLock) {
return xsMethodA(handle, sort);
}
}
protected static int methodB(final long handle) {
synchronized (myLock) {
return xsMethodB(handle);
}
}
Я создал дамп потока моего приложения, выполняющего вышеуказанный класс, и был очень удивлен, увидев это:
"http-8080-136" daemon prio=10 tid=0x00000000447df000 nid=0x70ed waiting for monitor entry [0x00007fd862aea000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodA(MyClass.java:750)
- locked <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.otherMethod(SomeOtherClass.java:226)
...
"http-8080-111" daemon prio=10 tid=0x00007fd87d1a0000 nid=0x70c8 waiting for monitor entry [0x00007fd86e15f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodB(MyClass.java:991)
- locked <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.yetAnotherMethod(SomeOtherClass.java:3231)
...
(я изменил имена классов и методов в случае простоты, поэтому не получаюсбит с толку глупыми именами.)
Кажется, что оба потока http-8080-136 и http-8080-111 получили блокировку на myLock
.Это тот же объект, что и адрес объекта тот же: 0x00007fd8a6b8c790
.В Java Runtime Specification говорится об этом ключевом слове synchronized
:
Синхронизированный оператор получает блокировку взаимного исключения (§17.1) от имени исполняющего потока, выполняет блок, затем снимает блокировку,Пока исполняющий поток владеет блокировкой, никакой другой поток не может получить блокировку .[ Спецификация языка Java, 14.19 ]
Так как это вообще возможно?
В потоке есть еще 44 потокасвалка "в ожидании" блокировки.Вот как это выглядит, если поток ожидает:
"http-8080-146" daemon prio=10 tid=0x00007fd786dab000 nid=0x184b waiting for monitor entry [0x00007fd8393b6000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodC(MyClass.java:750)
- waiting to lock <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.yetAnoterMethod2(SomeOtherClass.java:226)