есть ли разница, если поток ожидает освобождения монитора перед синхронизированным блоком или если он вызывает wait()

Я прочитал много документов о состояниях потоков, в некоторых из них говорится, что есть два разных состояния: заблокировано (до синхронизации) и ожидание (если вызовы ждут), в других говорится, что есть только одно состояние: ожидание. Более того, в некоторых документах говорится, что вы должны вызывать notify() для каждого ожидания(), и если вы этого не сделаете, то потоки, ожидающие(), никогда не будут иметь права на выполнение, даже если монитор разблокирован.


person dhblah    schedule 06.10.2010    source источник


Ответы (4)


Из вашего последнего предложения я вижу, что вы не совсем понимаете разницу между synchronized и wait()/notify().

По сути, у монитора есть блокировка и условие. Это почти ортогональные понятия.

  • Когда поток входит в блок synchronized, он получает блокировку. Когда поток покидает этот блок, он снимает блокировку. Только один поток может иметь блокировку на конкретном мониторе.

  • Когда поток, имеющий блокировку, вызывает wait(), он освобождает блокировку и начинает ожидать ее состояния. Когда поток, имеющий блокировку, вызывает notify(), один из потоков (все потоки в случае notifyAll()), ожидающих выполнения условия, получает право на выполнение (и начинает ожидать получения блокировки, поскольку уведомляющий поток все еще имеет ее).

Итак, ожидание получения блокировки (Thread.State.BLOCKED) и ожидание состояния монитора (Thread.State.WAITING) — это разные и независимые состояния.

Это поведение станет более понятным, если вы посмотрите на Класс Lock — реализует те же примитивы синхронизации, что и блок synchronized (с некоторыми расширениями), но обеспечивает четкое различие между блокировками и условиями.

person axtavt    schedule 06.10.2010
comment
Вы имеете в виду, что notify() изменяет состояние монитора? Но что тогда делает notifyAll()? Означает ли это, что у монитора есть набор условий, по одному для каждого потока, которым он управляет. Кроме того, как поток проверяет условие или блокировку, проверяет ли он бесконечный цикл (пока !monitor.lock) или (пока !monitor.condition[threadNum])? P.S. здесь я говорю о простых мониторах (Object), я не знаком с высокоуровневыми параллельными механизмами (кто-нибудь ими пользуется?) - person dhblah; 06.10.2010
comment
@gasan: Состояние монитора не является состоянием в обычном смысле, это примитив синхронизации, поэтому его нельзя изменить. У него просто есть набор потоков, ожидающих его. notifyAll() работает так же, как notify(), но для всех потоков, ожидающих выполнения условия. - person axtavt; 06.10.2010

Имеются два разных состояния: ЗАБЛОКИРОВАНО и ОЖИДАЮЩИЙ.

Часть о вечном ожидании, если вас никто не уведомит (или не прервет), верна.

person Thilo    schedule 06.10.2010

Стандартный документ здесь

Когда поток вызывает метод Object.wait, он освобождает полученный монитор и переходит в состояние WAITING (или TIMED_WAITING, если мы вызываем версии метода ожидания с тайм-аутом). Теперь, когда поток уведомляется notify() или notifyAll() вызовом того же объекта, тогда состояние ожидания потока заканчивается, и поток начинает пытаться восстановить все мониторы, которые он получил во время вызова ожидания. Одновременно может быть несколько потоков, пытающихся восстановить (или, возможно, получить впервые) свои мониторы. Если несколько потоков пытаются получить монитор конкретного объекта, то только один поток (выбранный планировщиком JVM) получает монитор, а все остальные потоки переводятся в состояние BLOCKED.

person jmj    schedule 06.10.2010
comment
Как вы думаете, почему «Object.wait» выпускает «все» потоки, полученные мониторами? Я думаю, что он снимает только эту блокировку объекта. Я это где-то читал, но не помню где. - person dhblah; 06.10.2010
comment
@gasan Я имел в виду, что он снимает все полученные блокировки, - person jmj; 06.10.2010
comment
да, именно об этом я и спрашиваю. Почему вы имеете в виду, что он снимает all блокировки. Я думаю, что он снимает только эту конкретную блокировку монитора. - person dhblah; 06.10.2010
comment
download.oracle.com/ javase/1.4.2/docs/api/java/lang/, интервал) - person jmj; 06.10.2010
comment
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+".

person Jingguo Yao    schedule 30.05.2013