Переход состояния Java-потока, ОЖИДАНИЕ БЛОКИРОВАТЬ или RUNNABLE?

Похоже, что существует несоответствие между SO-консенсусом и почти каждой диаграммой состояний потоков Java в Интернете; в частности, относительно перехода состояния состояния от WAITING после вызова notify() или notifyAll()...

  • WAITING никогда не переходит непосредственно в RUNNABLE
  • Поток WAITING, пока он не будет уведомлен... Затем он станет BLOCKED...
  • Как только этот поток будет уведомлен, он не будет запущен... Это состояние... заблокированное.

Итак, консенсус по SO: поток переходит из WAITING в BLOCKED после вызова notify() или notifyAll(); диаграмма ниже иллюстрирует этот переход зеленым цветом.

Вопрос

Почему большинство диаграмм состояний в Интернете иллюстрируют переход от WAITING в RUNNABLE, а не BLOCKED? Изображение красного цвета показывает неправильный переход; я что-то упускаю?

enter image description here

Ответ 1

Любая диаграмма, показывающая вызов notify, приводящий поток от WAITING к RUNNABLE, неверна (или использует неясный ярлык). Как только поток проснулся от notify (или даже из-под ложного пробуждения), ему нужно переустановить монитор объекта, на котором он ждал. Это состояние BLOCKED.

Состояние потока для потока, заблокированного в ожидании блокировки монитора. Тема в заблокированном состоянии ожидает блокировки монитора, чтобы войти в синхронизировать блок/метод или повторно ввести синхронизированный блок/метод после вызов Object.wait.

Это объясняется в javadoc Object#notify():

Пробужденная нить не сможет действовать до тех пор, пока текущая thread освобождает блокировку этого объекта.

и Object#wait()

Затем поток ждет, пока он не сможет повторно получить право собственности на монитор и возобновляет выполнение.

Ответ 2

В последнее время я сосредоточен на проблеме.

как документ Oracle Thread.State говорит, что мы можем использовать LockSupport.park(), чтобы поместить текущий поток в состояние "ОЖИДАНИЕ" или "TIMED_WAITING".

поэтому при попытке LockSupport.unpark() указанный поток вернется в "RUNNABLE" из "WAITING" /'TIMED_WAITING', (Я не уверен, пройдет ли он через состояние "BLOCKED" )

Ответ 3

Поток находится в состоянии WAITING в состоянии БЛОК, пока он не получит монитор, уведомив его и не станет RUNNABLE.

То же самое относится к TIMEDWAITING, он переходит в состояние БЛОК, если монитор удерживается каким-либо другим потоком, хотя указанное время прошло (ваша диаграмма должна быть исправлено)