есть ли разница, если поток ожидает освобождения монитора перед синхронизированным блоком или если он вызывает wait () - PullRequest
4 голосов
/ 06 октября 2010

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

Ответы [ 4 ]

13 голосов
/ 06 октября 2010

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

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

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

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

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

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

1 голос
/ 06 октября 2010

Есть два разных состояния ЗАБЛОКИРОВАНО и ОЖИДАНИЕ.

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

1 голос
/ 06 октября 2010

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

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

0 голосов
/ 30 мая 2013

С точки зрения Java ( Thread.State ) существует два разных состояния: ЗАБЛОКИРОВАНО и ОЖИДАНИЕ. Когда поток синхронизируется на объекте, он находится в состоянии BLOCKED. После того, как поток выполняет ожидание, он находится в состоянии ОЖИДАНИЯ.

На платформе Linux поток Java является собственным потоком ОС. Состояние потока ОС как для состояния BLOCKED, так и для состояния WAITING - это прерывистый режим сна. При проверке с помощью ps состояние для потоков BLOCKED и WAITING равно «Sl +».

...