web-dev-qa-db-fra.com

Y a-t-il réellement des fausses alarmes en Java?

Voir diverses questions liées au verrouillage et trouver (presque) toujours la boucle à cause de termes de wakeups parasites1 Je me demande si quelqu'un a vécu ce genre de réveil (en supposant un environnement matériel/logiciel décent, par exemple)?

Je sais que le terme 'faux' signifie aucune raison apparente, mais quelles peuvent être les raisons d'un tel événement?

(1 Remarque: je ne remets pas en question la pratique de la mise en boucle.)

Edit: Une question d'aide (pour ceux qui aiment les exemples de code):

Si j'ai le programme suivant et que je l'exécute:

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();
        }
    }
}

Que puis-je faire pour réveiller cette await de façon fallacieuse sans attendre pour toujours un événement aléatoire?

192
akarnokd

Le Wikipedia article sur les wakeups parasites a cette friandise:

La fonction pthread_cond_wait() sous Linux est implémentée à l'aide de l'appel système futex. Chaque appel système bloquant sous Linux revient brusquement avec EINTR lorsque le processus reçoit un signal. ... pthread_cond_wait() ne peut pas redémarrer l'attente, car elle risque de manquer un réveil en peu de temps après l'appel système futex. Cette condition de concurrence ne peut être évitée que si l'appelant recherche un invariant. Un signal POSIX générera donc un réveil parasite.

Résumé: si un processus Linux est signalé, ses threads en attente bénéficieront chacun d'un Nice, chaud réveil parasite.

Je l'achète. C'est une pilule plus facile à avaler que la raison généralement vague "c'est pour la performance".

192
John Kugelman

J'ai un système de production qui présente ce comportement . Un thread attend un signal indiquant qu'il y a un message dans la file d'attente . En période de forte activité, jusqu'à 20% des réveils sont parasites Ce fil est le seul consommateur des messages . Il s’exécute sur une machine Linux SLES-10 à 8 processeurs et est construit avec GCC 4.1.2 . Les messages sont à partir d'une source externe et sont traités de manière asynchrone car il y a des problèmes si mon système ne les lit pas assez rapidement.

21
Mr.Dirty.Birdy

Pour répondre à la question dans le titile - Oui! Ça arrive. Bien que le article de Wiki mentionne beaucoup de choses sur les réveils fantômes. 

Pensez-y. Comme tout code, les planificateurs de threads peuvent subir une panne temporaire en raison d’un événement anormal dans le matériel/logiciel sous-jacent. Bien sûr, il faut veiller à ce que cela se produise le plus rarement possible, mais comme il n’existe pas de logiciel 100% robuste, il est raisonnable de supposer que cela peut se produire et de veiller à la récupération en douceur si le planificateur le détecte (par exemple, en observant les battements de coeur manquants).

Maintenant, comment le planificateur pourrait-il récupérer, en tenant compte du fait que pendant la panne, il pourrait manquer certains signaux destinés à notifier les threads en attente? Si le planificateur ne fait rien, les fils "malchanceux" mentionnés resteront bloqués, en attendant toujours - pour éviter cela, le planificateur enverra simplement un signal à tous les fils en attente.

Cela rend nécessaire d'établir un "contrat" ​​indiquant que le fil en attente peut être notifié sans raison. Pour être précis, il y aurait une raison - une panne d'électricité du planificateur - mais puisque le fil est conçu (pour une bonne raison) pour ne pas se soucier des détails de l'implémentation interne du planificateur, il est probablement préférable de présenter cette raison comme étant "parasite".

Je lisais cette réponse de Source et la trouvais suffisamment raisonnable. Lire aussi

Les réveils parasites en Java et comment les éviter

PS: Le lien ci-dessus est celui de mon blog personnel qui contient des détails supplémentaires sur les faux wakeups. 

13
Aniket Thakur

Cameron Purdy a écrit un billet de blog il y a quelque temps sur le fait d'être frappé par le faux problème de réveil. Alors oui, ça arrive

Je suppose que c'est dans les spécifications (comme une possibilité) en raison des limitations de certaines des plateformes sur lesquelles Java est déployé? bien que je puisse me tromper!

8
oxbow_lakes

Juste pour ajouter ceci. Oui, cela arrive et j'ai passé trois jours à rechercher la cause d'un problème multi-threading sur une machine à 24 cœurs (JDK 6). 4 exécutions sur 10 ont vécu cela sans motif. Ce n'est jamais arrivé sur 2 ou 8 noyaux.

J'ai étudié du matériel en ligne et ce n’est pas un problème de Java mais un comportement rare mais attendu.

8
ReneS

https://stackoverflow.com/a/1461956/14731 contient une excellente explication de la nécessité de vous prémunir contre la surpopulation, même si le système d'exploitation sous-jacent ne les déclenche pas. Il est intéressant de noter que cette explication s’applique à plusieurs langages de programmation, y compris Java.

0
Gili