Est-ce que des réveils fallacieux en Java se produisent?

Voyant diverses questions liées au locking et trouvant (presque) toujours la «boucle à cause des termes de wakeups intempestifs», je me demande si quelqu’un a connu un tel réveil (en supposant un environnement matériel / logiciel décent, par exemple)?

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

( 1 Note: je ne remets pas en question la pratique en boucle.)

Edit: Une question d’assistance (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(Ssortingng[] 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 sans attendre un événement aléatoire?

L’ article de Wikipédia sur les wakeups illusoires a cette nouveauté:

La fonction pthread_cond_wait() sous Linux est implémentée en utilisant l’ futex système futex . Chaque appel système bloquant sur Linux renvoie brusquement avec EINTR lorsque le processus reçoit un signal. … pthread_cond_wait() ne peut pas redémarrer l’attente car il risque de manquer un véritable réveil dans le peu de temps écoulé en dehors de l’ futex système futex . Cette condition de course ne peut être évitée que par l’appelant qui recherche un invariant. Un signal POSIX générera donc un réveil erroné.

Résumé : Si un processus Linux est signalé, ses threads en attente bénéficieront chacun d’un réveil fantaisiste .

Je l’achète. C’est une pilule plus facile à avaler que la raison souvent vague «c’est pour la performance» souvent donnée.

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 queue. Dans les périodes de pointe, jusqu’à 20% des réveils sont parasites (c’est-à-dire qu’au réveil, il n’ya rien dans la file d’attente). Ce thread est le seul consommateur des messages. Il fonctionne sur un boîtier Linux SLES-10 à 8 processeurs et est construit avec GCC 4.1.2. Les messages proviennent 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.

Pour répondre à la question dans le titre – Oui! Bien que l’ article Wiki mentionne un bon nombre de réveils fallacieux, une bonne explication de ce que j’ai trouvé est la suivante –

Il suffit de penser à cela … comme tout code, le planificateur de threads peut rencontrer une panne temporaire en raison de quelque chose d’anormal se produisant dans le matériel / logiciel sous-jacent. Bien sûr, il faut veiller à ce que cela se produise aussi rarement que possible, mais comme il n’existe pas de logiciel 100% robuste, il est raisonnable de supposer que cela peut se produire et de faire une récupération progressive si le programmateur le détecte (par exemple, en observant les battements de coeur manquants).

Maintenant, comment le programmateur pourrait-il récupérer, en tenant compte du fait que pendant la panne, il pourrait manquer des signaux destinés à notifier les threads en attente? Si le programmateur ne fait rien, les threads “malchanceux” mentionnés se bloqueront, en attendant pour toujours – pour éviter cela, le programmateur enverrait simplement un signal à tous les threads en attente.

Cela rend nécessaire d’établir un “contrat” ​​que le thread en attente peut être notifié sans raison. Pour être précis, il y aurait une raison – blackout du planificateur – mais comme le thread est conçu (pour une bonne raison) pour ne pas comprendre les détails de la mise en œuvre interne du planificateur, cette raison est probablement meilleure.

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

De faux réveils en Java et comment les éviter .

Juste pour append ceci. Oui, cela arrive et j’ai passé trois jours à chercher la cause d’un problème de multi-threading sur une machine à 24 cœurs (JDK 6). 4 des 10 exécutions ont connu cela sans aucun schéma. Cela n’est jamais arrivé sur 2 cœurs ou 8 cœurs.

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

Cameron Purdy a écrit un article de blog il y a quelque temps sur le fait d’avoir été touché par le faux problème de réveil. Alors oui, ça arrive

Je suppose que c’est dans la spécification (en tant que possibilité) en raison des limitations de certaines des plates-formes sur lesquelles Java est déployé? bien que je puisse me tromper!

https://stackoverflow.com/a/1461956/14731 contient une excellente explication des raisons pour lesquelles vous devez vous prémunir contre les réveils intempestifs 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.