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

Если у меня есть фрагмент кода ниже

synchronized (this)
{
    System.out.println("Waiting for return key.");
    scanner.nextLine();
    System.out.println("Return key pressed.");
    notify();
    Thread.sleep(5000);
}

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

Тот же вопрос идет с notify а также notifyall, после того, как один поток проснулся и получил блокировку, это ожидание всех других потоков становится занятым?

3 ответа

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

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

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

synchronized (lockObject) {
    // ...
    while (!condition) {
        lockObject.wait();
    }
    // object is now in desired state
}

Смотрите также: Параллелизм Java на практике, глава 14.2

Поток может ожидать объект только тогда, когда он СОБСТВЕННО монитор объекта. Как только первый поток уведомляет, второй поток просыпается, но ничего не делает. Единственное, что здесь происходит, это то, что "поток будет удален из списка потоков, ожидающих объекта. Он оставлен на усмотрение ОС для планирования его выполнения. ОС может выбрать НЕ выполнять его в течение некоторого времени. Поток не выполняет" t busy-wait. Он просто будет в наборе потоков, ожидающих планирования.

Как указывает @Holger, любой поток, который вызывает wait(), снимает блокировку объекта. Как только он получает уведомление, он должен "конкурировать" и повторно получить блокировку на объекте. Повторное получение блокировки не происходит, когда notify() вызывается потоком, который удерживает блокировку. Это происходит, когда этот поток выходит из своего синхронизированного блока.

Другие вопросы по тегам