Как понять метод ожидания и уведомления в потоке Java? - PullRequest
7 голосов
/ 01 января 2012

Я очень запутался в этих двух описаниях:

  1. «Метод ожидания блокирует вызывающий поток и снимает блокировку монитора»
  2. «Метод уведомления разблокирует один ожидающий поток, но не снимает блокировку монитора»

Вот мои вопросы:

  1. Я знаю, что у каждого объекта в Java есть блокировка, но что означает «блокировка монитора»? это то же самое, что и замок объекта?

  2. Почему метод уведомления должен отказаться от блокировки монитора?

  3. Если я попытаюсь сделать объект ожидающим со следующим кодом:

    class simpleTask extends Thread
    {
        int waitingTime;
    
        public simpleTask(int waitingTime)
        {
            this.waitingTime = waitingTime;
        }
    
        public void run()
        {
            synchronized(this) // this is a reference of current object
            {
            try {
                this.wait(waitingTime);
            } catch (InterruptedException e) {
            // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

Как и в первом приведенном выше описании, означает ли это, что текущий объект заблокирован синхронизированным ключевым словом, а затем метод wait снимает блокировку?

Ответы [ 3 ]

7 голосов
/ 01 января 2012

Я знаю, что у каждого объекта в Java есть блокировка, но что означает «блокировка монитора»? это то же самое, что и блокировка объекта?

Да, это одно и то же. Их также иногда называют «мьютексом» объекта и «примитивной блокировкой» объекта. (Но когда кто-то говорит о Lock, он говорит о этом Java-интерфейсе ... который представляет собой другой механизм блокировки.)

Почему метод notify должен отказаться от блокировки монитора?

Метод notify не не снимает блокировку. Ответственность за снятие блокировки лежит на вашем коде (то есть оставить синхронизированный блок или вернуться из синхронизированного метода) после возврата вызова notify.

Почему это необходимо? Потому что любой другой поток, который в данный момент ожидает этой блокировки (в вызове wait(...)), должен повторно получить эту блокировку до завершения вызова wait.

Почему они выглядят так: notify / wait? Чтобы их можно было использовать для реализации условных переменных.

Как и в первом приведенном выше описании, означает ли это, что текущий объект заблокирован синхронизированным ключевым словом, а затем метод wait снимает блокировку?

Это правильно. Когда поток вызывает someObject.wait(), его блокировка на someObject освобождается ... и затем повторно запрашивается (тем же потоком) до возврата вызова wait(). Конечно, тем временем блокировка someObject может была получена и освобождена несколько раз другими потоками. Дело в том, что когда возвращается wait, поток, вызвавший wait, будет иметь блокировку.

0 голосов
/ 01 января 2012

Монитор - это тип конструкции синхронизации.

Причина, по которой ожидание снимает блокировку, заключается в том, что другие потоки могут получить блокировку, например другие потоки, которые могут захотеть ждать. Кроме того: обычно поток, который пробуждает другие потоки, блокируется перед выпуском любых потоков, чтобы предотвратить состояние гонки.

Для получения дополнительной информации вам следует изучить переменные условия (т.е. condvars).

0 голосов
/ 01 января 2012
  1. Да, блокировка монитора совпадает с блокировкой объекта. Если вы делаете synchronized (object), это замок.

  2. В вашем примере текущий объект откажется от блокировки во время ожидания, вызов wait() откажется от блокировки. В другом потоке вызывается notify(), чтобы разбудить объект, и когда вызов wait() возвращается, он снова удерживает блокировку.

...