Действительно ли возникают побочные пробуждения?

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

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

( 1 Примечание: я не стану сомневаться в практике циклирования.)

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

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

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 ложно, не ожидая навсегда случайного события?

Ответ 1

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

Функция pthread_cond_wait() в Linux реализована с использованием системного вызова futex. Каждый системный вызов блокировки в Linux внезапно возвращается с помощью EINTR, когда процесс получает сигнал.... pthread_cond_wait() не может перезапустить ожидание, потому что оно может пропустить реальное пробуждение за малое время, когда оно было вне системного вызова futex. Это условие гонки можно избежать, только если вызывающий абонент проверит инвариант. Таким образом, сигнал POSIX генерирует ложное пробуждение.

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

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

Ответ 2

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

Ответ 3

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

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

Теперь, как можно было бы планировать восстановление, учитывая, что во время затемнения он может пропустить некоторые сигналы, предназначенные для уведомления ожидающих потоков? Если планировщик ничего не делает, упомянутые "несчастливые" потоки будут просто зависать, ожидая вечно - чтобы этого избежать, планировщик просто отправил сигнал всем ожидающим потокам.

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

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

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

Ответ 4

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

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

Ответ 5

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

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