Я прочитал много документов о состояниях потоков, в некоторых из них говорится, что есть два разных состояния: заблокировано (до синхронизации) и ожидание (если вызовы ждут), в других говорится, что есть только одно состояние: ожидание. Более того, в некоторых документах говорится, что вы должны вызывать notify() для каждого ожидания(), и если вы этого не сделаете, то потоки, ожидающие(), никогда не будут иметь права на выполнение, даже если монитор разблокирован.
есть ли разница, если поток ожидает освобождения монитора перед синхронизированным блоком или если он вызывает wait()
Ответы (4)
Из вашего последнего предложения я вижу, что вы не совсем понимаете разницу между synchronized
и wait()
/notify()
.
По сути, у монитора есть блокировка и условие. Это почти ортогональные понятия.
Когда поток входит в блок
synchronized
, он получает блокировку. Когда поток покидает этот блок, он снимает блокировку. Только один поток может иметь блокировку на конкретном мониторе.Когда поток, имеющий блокировку, вызывает
wait()
, он освобождает блокировку и начинает ожидать ее состояния. Когда поток, имеющий блокировку, вызываетnotify()
, один из потоков (все потоки в случаеnotifyAll()
), ожидающих выполнения условия, получает право на выполнение (и начинает ожидать получения блокировки, поскольку уведомляющий поток все еще имеет ее).
Итак, ожидание получения блокировки (Thread.State.BLOCKED) и ожидание состояния монитора (Thread.State.WAITING) — это разные и независимые состояния.
Это поведение станет более понятным, если вы посмотрите на Класс Lock
— реализует те же примитивы синхронизации, что и блок synchronized
(с некоторыми расширениями), но обеспечивает четкое различие между блокировками и условиями.
notifyAll()
работает так же, как notify()
, но для всех потоков, ожидающих выполнения условия.
- person axtavt; 06.10.2010
Имеются два разных состояния: ЗАБЛОКИРОВАНО и ОЖИДАЮЩИЙ.
Часть о вечном ожидании, если вас никто не уведомит (или не прервет), верна.
Когда поток вызывает метод
Object.wait
, он освобождает полученный монитор и переходит в состояниеWAITING
(илиTIMED_WAITING
, если мы вызываем версии метода ожидания с тайм-аутом). Теперь, когда поток уведомляетсяnotify()
илиnotifyAll()
вызовом того же объекта, тогда состояние ожидания потока заканчивается, и поток начинает пытаться восстановить все мониторы, которые он получил во время вызова ожидания. Одновременно может быть несколько потоков, пытающихся восстановить (или, возможно, получить впервые) свои мониторы. Если несколько потоков пытаются получить монитор конкретного объекта, то только один поток (выбранный планировщикомJVM
) получает монитор, а все остальные потоки переводятся в состояниеBLOCKED
.
all
блокировки. Я думаю, что он снимает только эту конкретную блокировку монитора.
- person dhblah; 06.10.2010
The thread releases ownership of this monitor
только this
контролировать, а не `все`
- person dhblah; 06.10.2010
С точки зрения Java (Thread.State ), есть два разных состояния: BLOCKED и WAITING . Когда поток синхронизируется с объектом, он находится в состоянии BLOCKED. После выполнения потока ожидания он находится в состоянии ОЖИДАНИЯ.
На платформе Linux поток Java является собственным потоком ОС. Состояние потока ОС для состояний BLOCKED и WAITING — Прерываемый спящий режим. При проверке с помощью ps состояние потоков BLOCKED и WAITING равно "Sl+".