Вопрос по multithreading, java – Случаются ли ложные пробуждения в Java на самом деле?

193

Просмотр различных вопросов, связанных с блокировкой, и (почти) всегда нахождение цикла «из-за ложных пробуждений»; термины1 Интересно, кто-нибудь сталкивался с таким пробуждением (например, при условии достойной аппаратной / программной среды)?

Я знаю термин «ложный» означает отсутствие видимой причины, но каковы могут быть причины такого рода события?

(1 Примечание. Я не ставлю под сомнение практику зацикливания.)

Edit: Вспомогательный вопрос (для тех, кто любит примеры кода):

Если у меня есть следующая программа, и я запускаю ее:

public class Spurious {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition cond = lock.newCondition();
        lock.lock();
        try {
            try {
                cond.await();
                System.out.println("Spurious wakeup!");
            } catch (InterruptedException ex) {
                System.out.println("Just a regular interrupt.");
            }
        } finally {
            lock.unlock();
        }
    }
}

Что я могу сделать, чтобы разбудить этоawait с энтузиазмом, не ожидая вечно случайного события?

Для JVM, которые работают в системах POSIX и используютpthread_cond_wait() настоящий вопрос"Why does pthread_cond_wait have spurious wakeups?". Flow

Ваш Ответ

6   ответов
21

которая демонстрирует это поведение. Поток ожидает сигнала о том, что в очереди есть сообщение. В периоды занятости до 20% пробуждений являются ложными (то есть, когда они просыпаются, в очереди ничего нет). Эта тема является единственным потребителем сообщений. Он работает на 8-процессорной коробке Linux SLES-10 и построен на GCC 4.1.2. Сообщения приходят из внешнего источника и обрабатываются асинхронно, потому что возникают проблемы, если моя система не читает их достаточно быстро.

193

статья о ложных пробуждениях имеет этот кусок:

The pthread_cond_wait() function in Linux is implemented using the futex system call. Each blocking system call on Linux returns abruptly with EINTR when the process receives a signal. ... pthread_cond_wait() can't restart the waiting because it may miss a real wakeup in the little time it was outside the futex system call. This race condition can only be avoided by the caller checking for an invariant. A POSIX signal will therefore generate a spurious wakeup.

Summary: Если процесс Linux сигнализирует, его ожидающие потоки будут наслаждаться приятным, горячимspurious wakeup.

Я покупаю это. Эту таблетку легче проглотить, чем обычно расплывчатую таблетку "для эффективности". причина часто приводится.

Error: User Rate Limit Exceededstackoverflow.com/questions/1461913/…
Error: User Rate Limit Exceededpubs.opengroup.org/onlinepubs/7908799/xsh/…Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededpthreadError: User Rate Limit Exceeded
Error: User Rate Limit Exceededfutex()Error: User Rate Limit ExceededEINTRError: User Rate Limit Exceededpthread_cond_wait()Error: User Rate Limit Exceeded
8

это случилось, и я потратил три дня на поиск причины многопоточности на 24-ядерном компьютере (JDK 6). 4 из 10 казней пережили это без какого-либо паттерна. Это никогда не происходило на 2 или 8 ядер.

Изучил некоторые онлайн-материалы, и это не проблема Java, а общее редкое, но ожидаемое поведение.

Error: User Rate Limit Exceededdocs.oracle.com/javase/6/docs/api/java/lang/… ?
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededblog.xceptance.com/2011/05/06/spurious-wakeup-the-rare-event
8

Кэмерон Перди написалСообщение блога Некоторое время назад о том, чтобы быть пораженным ложной проблемой пробуждения. Да так бывает

Я предполагаю, что это в спецификации (как возможность) из-за ограничений некоторых платформ, на которых развернута Java? хотя я могу ошибаться!

Error: User Rate Limit ExceededstrictError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded akarnokd
Error: User Rate Limit Exceeded akarnokd
0

https://stackoverflow.com/a/1461956/14731 содержит отличное объяснение того, почему вы должны защититься от ложных пробуждений, даже если базовая операционная система не вызывает их. Интересно отметить, что это объяснение применимо ко многим языкам программирования, включая Java.

13

Yes! это случается. ХотяСтатья в вики упоминает много о ложных пробуждениях, хорошее объяснение того же, с чем я столкнулся, заключается в следующем -

Just think of it... like any code, thread scheduler may experience temporary blackout due to something abnormal happening in underlying hardware / software. Of course, care should be taken for this to happen as rare as possible, but since there's no such thing as 100% robust software it is reasonable to assume this can happen and take care on the graceful recovery in case if scheduler detects this (eg by observing missing heartbeats).

Now, how could scheduler recover, taking into account that during blackout it could miss some signals intended to notify waiting threads? If scheduler does nothing, mentioned "unlucky" threads will just hang, waiting forever - to avoid this, scheduler would simply send a signal to all the waiting threads.

This makes it necessary to establish a "contract" that waiting thread can be notified without a reason. To be precise, there would be a reason - scheduler blackout - but since thread is designed (for a good reason) to be oblivious to scheduler internal implementation details, this reason is likely better to present as "spurious".

Я читал этот ответ отИсточник и нашел это достаточно разумным. Также прочитайте

Ложные пробуждения в Java и как их избежать.

PS: выше ссылка на мой личный блог, в котором есть дополнительная информация о ложных пробуждениях.

Похожие вопросы