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

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

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

Вопрос

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

4 ответа

Решение

Любая диаграмма, которая показывает notify неправильный вызов переноса потока из ОЖИДАНИЯ в RUNNABLE (или использование невыясненного ярлыка). Как только нить пробуждается от notify (или даже из-за ложного пробуждения) ему необходимо снова заблокировать монитор объекта, на котором он ожидал. Это BLOCKED государство.

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

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

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

а также Object#wait()

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

Поток в состоянии ОЖИДАНИЯ переходит в состояние БЛОК, пока он не получит монитор путем уведомления и не станет RUNNABLE.

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

Я фокусируюсь на проблеме в последнее время.

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

поэтому, когда вы попытаетесь использовать LockSupport.unpark (), указанный поток вернется к "RUNNABLE" из "WAITING" / "TIMED_WAITING". (Я не уверен, пройдет ли он через состояние "ЗАБЛОКИРОВАНО")

Стоит отметить, что это также верно для метода во время состояния, в то время как в lock.wait()метод.

Thread.interrupt()метод сначала сделает WAITINGнить BLOCKEDс isInterruptedфлаг установлен в значение true, и только после повторного получения блокировки прерванный поток сможет бросить InterruptedException(это очевидно, так как он не может обрабатывать исключение, продолжая выполнение без монопольной блокировки ранее). (пример здесь )

Просто сказать

Всегда WAITING -> BLOCKEDчтобы иметь возможность снова конкурировать за блокировку, а после этого получить ее в конце концов и запустить ее код RUNNABLE.

Другие вопросы по тегам