Мое понимание блоков Java synchronized() заключается в том, что если поток уже владеет блокировкой объекта, он может войти в другой блок, синхронизированный с тем же объектом (синхронизация с повторным входом). Ниже я считаю, что JVM использует счетчик ссылок для увеличения/уменьшения количества раз, когда поток получал блокировку, и что блокировка снимается только тогда, когда счетчик равен нулю.
Итак, мой вопрос: если кто-то столкнется с фрагментом кода, который выглядит так:
synchronized(this)
{
if (condition == WAITING)
{
synchronized(this)
{
condition = COMPLETE;
notify();
try
{
wait();
}
catch(InterruptedException e)
{
}
}
}
else
condition = READY;
}
что конкретно происходит при вызове wait()? Он просто уменьшает счетчик или освобождает блокировку независимо от счетчика?
В первом случае мне кажется, что он вызовет взаимоблокировку, если произошел повторный вход в блокировку, потому что он по-прежнему будет владеть блокировкой и, таким образом, будет вечно ждать другого потока, который ожидает его.
Во втором случае я вообще не вижу смысла во втором синхронизированном блоке.
В документации для wait() говорится
«Текущий поток должен владеть монитором этого объекта. Поток освобождает владение этим монитором и ждет, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы проснуться либо с помощью вызова метода уведомления, либо метода notifyAll. Затем поток ждет, пока он может повторно получить право собственности на монитор и возобновить выполнение»,
поэтому я думаю, что второй случай правильный, но я могу ошибаться. Так я что-то упустил, или я просто наткнулся на лишний синхронизированный блок, который можно так же легко удалить из кода?