Java: все ли мониторы освобождаются, когда поток ожидает объекта? - PullRequest
18 голосов
/ 07 июня 2011

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

Но что происходит с другими мониторами, которые поток удерживает, когда вызывает wait?

Рассмотрим этот пример:

   Object a = // ...
   Object b = // ...

   synchronized(a)
   {
       synchronized(b)
       {
           b.wait();
           // continue
       }
   }

Когда поток вызывает b.wait(), разблокирует ли он и a и b или только b?

Ответы [ 3 ]

16 голосов
/ 07 июня 2011

Только b.

Авторитетным источником вопросов такого типа является спецификация языка Java. Соответствующим разделом в этом случае является 17.8 Наборы ожидания и уведомления :

Пусть thread t будет потоком , выполняющим метод ожидания для объекта m , и пусть n будет количеством действий блокировки на t на m , которые не были сопоставлены с действиями разблокировки. Происходит одно из следующих действий.

  • [...]
  • В противном случае происходит следующая последовательность действий:

    1. Поток t добавляется к набору ожидания объекта m и выполняет n действий по разблокировке в m .
    2. [...]
11 голосов
/ 07 июня 2011

Из документации API Java класса объекта :

Текущий поток должен иметь монитор этого объекта.Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify, либо метода notifyAll.Затем поток ожидает, пока не получит право владения монитором, и возобновит выполнение.

Таким образом, вызов b.wait() снимает блокировку только на b.

7 голосов
/ 07 июня 2011

AFAIK только б. Это классический источник тупиков.

...