Если wait () генерирует InterruptedException, ожидает ли поток, пока он не получит монитор объекта? - PullRequest
0 голосов
/ 02 мая 2018

Например:

public synchronized Object get() {
    while (result == null) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
            // Do we own the monitor of this object?
        }
    }
    return result;
}

Когда e.printStackTrace() выполняется, мы гарантируем, что владеем монитором объекта?

Ссылка говорит, что когда wait() возвращается после вызова notify() или notifyAll(), поток ожидает, пока не получит монитор объекта. Но как насчет случая, когда wait() выдает исключение?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Да. Фактически, это InterruptedException выбрасывается после повторного приобретения монитора.

См. Подождите в JLS :

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

  • Если n равно нулю (т. Е. Поток t еще не имеет блокировки для target m), затем генерируется исключение IllegalMonitorStateException.

  • Если это временное ожидание, а аргумент nanosecs находится вне диапазона 0-999999 или аргумент в миллисекундах отрицательный, то IllegalArgumentException выдается.

  • Если поток t прерывается, генерируется исключение InterruptedException и Состояние прерывания t установлено на false.

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

    1. Поток t добавляется в набор ожидания объекта m и выполняет n разблокировку действия на м.

    2. Поток t не выполняет никаких дальнейших инструкций, пока он не был удалены из набора ожидания м. Поток может быть удален из набора ожидания из-за любого из следующих действий, и возобновится когда-нибудь потом:

      • Действие уведомления, выполняемое для m, в котором t выбрано для удаление из набора ожидания.

      • УведомлениеВсе действия выполняются на м.

      • Действие прерывания, выполняемое для t .

      • Если это временное ожидание, внутреннее действие удаляет t из ожидания m набор, который происходит по крайней мере, миллисекунд миллисекунд плюс наносек наносекунды с начала этого действия ожидания.

      • Внутреннее действие по реализации. Реализации разрешено, хотя и не поощряется, выполнять "ложные пробуждения", то есть удалить потоки из наборов ожидания и, таким образом, включить возобновление без явных инструкций.

    3. Поток t выполняет n блокировочных действий на м.

    4. Если поток t был удален из ожидания m, установленного на шаге 2, из-за прерывание, затем состояние прерывания t устанавливается на false и ожидание метод выдает InterruptedException.

0 голосов
/ 02 мая 2018

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

Здесь лучше бросить InterruptedException вызывающей стороне, а не есть ее. Ваша цель здесь состоит в том, чтобы быстро выйти и сообщить вызывающему абоненту, что произошло прерывание, чтобы оно могло обернуться. Еда здесь также, кажется, означает, что вы снова возвращаетесь к циклу while. Прерывание используется java.util.concurrent для реализации отмены, особенно если вы используете инструменты java.util.concurrent, имеет смысл написать код, совместимый с ними.

...