Подтвердить что ты не робот

Wait (long timeout) в цикле while?

Я читал, что вы должны помещать вызовы Object.wait() в Java в цикле while. Причина в том, что этот поток может быть разбужен, и условие, которое вы ожидали оповестить, по-прежнему ложно (ложное пробуждение).

Как насчет Object.wait(long timeout). Здесь вы не хотите зацикливаться на этом состоянии, так как вы хотите, чтобы он отключился после указанного количества времени. Но если вы не поместите его в цикл, то как вы можете убедиться, что он не будет разбужен раньше?

4b9b3361

Ответ 1

Но если вы не ставите его в цикле, то как вы можете убедиться, что он не проснется раньше?

Это недостаток в Java IMO, хотя, возможно, это недостаток в поддержке базового потока в различных вариантах ОС. Я подозреваю, что Java знает, ожидалось ли время ожидания или нет, но нет возможности, чтобы вызывающий мог понять это без повторного тестирования состояния и, в частности, проверки времени. Некрасиво.

Таким образом, вам нужно будет поместить wait(long timeout) в цикл while, а также проверить, прошло ли время за период ожидания. Я не знаю другого способа добиться этого.

long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
while (!condition) {
    long waitMs = timeoutExpiredMs - System.currentTimeMillis();
    if (waitMs <= 0) {
       // timeout expired
       break;
    }
    // we assume we are in a synchronized (object) here
    object.wait(waitMs);
    // we might get improperly awoken here so we loop around to see if we timed out
}

Ответ 2

long deadline = now() + timeout;

synchronized(lock)

    while( !condition() && now()<deadline )
        lock.wait( deadline - now() );

    if(condition())
        ...
    else // timeout
        ...

Ответ 3

это потому, что у java есть мониторы стиля Mesa вместо мониторов стиля Hoare. Таким образом, вам нужно подождать цикл ожидания. Пожалуйста, найдите строку "По этой причине обычно необходимо заключить каждую операцию ожидания в цикле, подобном этому" на веб-странице follwing,

http://en.wikipedia.org/wiki/Monitor_(synchronization)#Nonblocking_condition_variables

.если это были мониторы стиля Хоар, тогда вы могли бы поставить свое ожидание в if. Я скоро добавлю детали мониторов Mesa. Это не недостаток Java. Оба типа мониторов имеют преимущества и недостатки.

Ответ 4

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

В основном вы ждете в цикле, потому что вам нужно проверить текущее состояние с сохраненной блокировкой, чтобы иметь возможность сказать, что происходит. Наличие таймаута не меняет этого. Тайм-аут - это механизм безопасности, поэтому, если уведомление пропущено, нить не будет вечно вешать. Если время ожидания там обычно не требует каких-либо конкретных действий, просто восстановите блокировку, перейдите к телу цикла и проверьте состояние трещины как обычно.

И это не ошибка Java, так работают pthreads.